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:
- '*/*'
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With