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:
- '*/*'
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.