Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I return errors on an AWS Lambda function written in Node.js through the AWS API Gateway using the Serverless framework?

I'm writing an API for internal use, and for the first time I'm using the serverless framework. I'm writing a Lambda function in Node.js, and using the AWS API Gateway to connect to it.

In some cases I want to return a custom error message, and I'm trying to write a function that would allow me to do that. Right now, any time the Lambda process fails, I get a standard message from the API. In the code, if I try to kill the process using process.exit(1), I get a generic error, even if I've already returned an error using callback():

{
    "message": "Internal server error"
}

If I don't use process.exit(1), I see the error I returned via callback() in the logs, but the process continues, ultimately timing out:

{
    "message": "Endpoint request timed out"
}

I've tried a few different ways of returning an error using the callback() method, but so far I haven't been successful. I've tried this method:

async function return_error(callback, context, error, returnCode){
  console.error("FATAL ERROR: ", error);
  let ErrorObj = {
    errorType : "InternalServerError",
    httpStatus : 500,
    requestId : context.awsRequestId,
    errorMessage : error
}
  callback(JSON.stringify(ErrorObj));
  process.exit(1);
}

and this one:

async function return_error(callback, error, returnCode){
  console.error("FATAL ERROR: ", error);
  callback({
    isBase64Encoded: false,
    statusCode: returnCode,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({"Error Message:": error})
  }, null);
  process.exit(1);
}

(Sorry about the minor syntax changes between the two.)

So far, I haven't been able to return any error to the user via the API. My error always get's logged, and the function continues. Any help would be appreciated. Thank you!

For reference, the relevant parts of my serverless.yml file:

service: #Name of service


provider:
  name: aws
  runtime: nodejs8.10
  role: #ARN of Iam role

functions:
  screenshot:
    handler: #Name of handler
    timeout: 30
    memorySize: 1280
    reservedConcurrency: 10
    events:
      - http: 
          method: get
          path: #path
          contentHandling: CONVERT_TO_BINARY
          authorizer:
            type: aws_iam

plugins:
  - serverless-plugin-chrome
  - serverless-apigw-binary
  - serverless-apigwy-binary
package:
  exclude:
    - node_modules/puppeteer/.local-chromium/** 

custom:
  apigwBinary:
    types:
      - '*/*'
like image 792
bfissa Avatar asked Nov 16 '18 20:11

bfissa


People also ask

How do I return a response from Lambda to API gateway?

There is no need to map the Lambda function response to its proper HTTP response. To return the result to the client, set up the integration response to pass the endpoint response through as-is to the corresponding method response. Or you can map the endpoint response data to the method response data.

How do you check Lambda error?

To troubleshoot Lambda code errors You can use CloudWatch to view all logs generated by your function's code and identify potential issues. For more information, see Accessing Amazon CloudWatch Logs for AWS Lambda.

How do I send error response in Lambda?

For API Gateway to pass the error type (for example, InvalidParameterException ), as part of the response to the client, the Lambda function must include a header (for example, "X-Amzn-ErrorType":"InvalidParameterException" ) in the headers property.


1 Answers

AWS error callbacks for Node.js do not work as advertised. According to the docs, all one needs to do is ensure custom errors extend the Error prototype. However, after over 10 hours of testing, I've found this is completely untrue.

The only way to return an error callback that will return anything other than {"message": "Internal server error"} (i.e. if you have your Lambda function triggered from the API gateway) is to callback the error as though it were a success.

TL;DR: callback(errorResponse, null) does not work, but callback(null, errorResponse) does.

like image 68
Nick Wehner Avatar answered Sep 22 '22 14:09

Nick Wehner