Custom exception name instead of UserLambdaValidationException

Viewed 1131

I use the Pre sign-up trigger of Cognito to validate the user registration. If some validation fails the function responses with a custom error. The client only receive the UserLambdaValidationException as ErrorCode.

Is there a way to receive the custom error name instead?

Current using sample:

exports.handler = function(event, context, callback) {                
  function AccountAlreadyExistsError(message) {
    this.name = "AccountAlreadyExistsError";
    this.message = message;
  }
  AccountAlreadyExistsError.prototype = new Error();

  const error = new AccountAlreadyExistsError("Account is in use!");
  callback(error);
};

I want to get AccountAlreadyExistsError in our client instead of UserLambdaValidationException.

2 Answers

You can customise exception headers only if it is a Lambda Proxy, with the API Gateway (x-amzn-errortype header), in any other case you need to parse the exception message to get your custom exception, here is an example how I manage exceptions for Cognito lambda triggers, it's just to show you the idea:

/*
  Lambda Code, could be in a Lambda layer
*/
const EXCEPTION_TYPE_DELIMITER = "etype"
const EXCEPTION_MESSAGE_DELIMITER = "emsg";

const beTagged = (tag, txt) => {
  return "<" + tag + ">" + txt + "</" + tag + ">";
};

class UserNotAllowedException extends Error {
   constructor (message) {
     super(beTagged(EXCEPTION_MESSAGE_DELIMITER, message))
     Error.captureStackTrace(this, this.constructor);
     this.name = beTagged(EXCEPTION_TYPE_DELIMITER, this.constructor.name);
   }
}

exports.handler = async (event, context, callback) => {
    // Your logic, etc..  
    throw new UserNotAllowedException("You are blocked :(");
}

Here is the parser

/*
  Client Code
*/
const EXCEPTION_TYPE_DELIMITER_REGEX = /<etype>(.*?)<\/etype>/g;
const EXCEPTION_TYPE_UNTAG_REGEX = /<\/?etype>/g;
const EXCEPTION_MESSAGE_DELIMITER_REGEX = /<emsg>(.*?)<\/emsg>/g;
const EXCEPTION_MESSAGE_UNTAG_REGEX = /<\/?emsg>/g;

const untag = (txt, delimiterRegex, untagRegex) => {
  return txt.match(delimiterRegex).map(etype => {
    return etype.replace(untagRegex,"");
  })[0];
};

const resolveException = (exceptionMessage) => {
    const exceptionType = untag(exceptionMessage, EXCEPTION_TYPE_DELIMITER_REGEX, EXCEPTION_TYPE_UNTAG_REGEX);
    const exceptionMessage = untag(exceptionMessage, EXCEPTION_MESSAGE_DELIMITER_REGEX, EXCEPTION_MESSAGE_UNTAG_REGEX);
    // Your logic to determine what exception is the exceptionType
    return new YourResolvedException(exceptionMessage);
};

try {
   // This guy should throw the exception
   return await Auth.signUp(params);
} catch (e) {
  // Expected message from Cognito Lambda Trigger
  // PreSignUp failed with error <etype>UserNotAllowedException</etype>: <emsg>You are blocked :(</emsg>.
  // For example, here your custom exception resolver
  throw resolveException(e.message);
}

It can be done in a thousand ways, but the best thing for us would be if the AWS services were able to fully customise the exceptions without so much hassle.

Regards!

Related