Callback with new Error('[status] message') always results in a 502 response
See original GitHub issueThis is a Bug report
When calling callback
inside a handler with an Error-object always results in 502 Bad Gateway
response. Even though the error-object is formatted as stated in the docs.
Description
I’ve been fiddling around with the framework, and I must say I’m impressed. And my next project will probably be powered by this library. Thanks for that!
But I can’t seem to get responding with error to work correctly.
I have a simple handler, a webhook, that get invoked on a http-post request. It does a few checks on the data passed in. If everything is fine I just call callback(null, { statusCode: 200, ... })
which works great.
But when I see that something is wrong I want to return a 400 Bad Request
or 403 Forbidden
-response. So I go like this: callback(new Error('[400] Bad Request')
, with the Error-object as the first argument, as I’ve read in the docs.
And the way I read the docs this should magically be transformed into a 400
-response. But when I try my endpoint with malformed or missing data, all I get is a 502 Bad Gateway
-response.
I’ve also tried the example repo aws-node-github-webhook-listener. But I got the same result.
Here’s a simplified version of my code:
handler.js
:
'use strict'
const checkData = require('./checkData');
module.exports.webhook = (event, context, callback) => {
const isValid = checkData(event);
if (!isValid) {
return callback(new Error('[400] Bad request'));
}
return callback(null, { statusCode: 200, body: JSON.stringify({ message: 'OK' }) });
};
serverless.yml
:
service: webhook
provider:
name: aws
runtime: nodejs6.10
functions:
webhook:
handler: handler.webhook
events:
- http:
path: webhook
method: post
cors: true
And if I check the logs ($ serverless logs -f webhook
) it looks like this:
START RequestId: <request id> Version: $LATEST
2017-08-18 00:47:21.371 (+02:00) <request id> {"errorMessage":"[400] Bad request","errorType":"Error","stackTrace":["module.exports.webhook (/var/task/handler.js:8:14)"]}
END RequestId: <request id>
REPORT RequestId: <request id> Duration: 3.94 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 19 MB
Hopefully this is just me misinterpreting the documentation. And if so I would gladly like to help and try updating the documentation and maybe clarify what’s going on.
Additional Data
- Serverless Framework Version you’re using: ^1.20.1
- Operating System: OSX
- Stack Trace: -
- Provider Error messages: See above
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (6 by maintainers)
You are using the AWS Lambda proxy semantics of Lambda/APIG. That means, that the Lambda MUST return a Lambda proxy compatible response which is in turn transformed to a HTTP response.
If you let the Lambda fail by using the callback with an Error object, the Lambda itself fails, but this failure cannot be transformed internally to a HTTP response anymore. So you get a 502, which means “malformed lambda proxy response”, because a failing Lambda returns a stringified error object including the callstack.
If you want to respond with HTTP errors in that case, you have to encode the HTTP error as successful Lambda response -> You can think of that in a way that you want to respond on purpose with an error. If a Lambda crashes and you trigger the callback with an Error eventually - or it is internally catched, it is more kind of an unexpected condition.
Ok. To come to the conclusion 😉 You should return errors that you want to be specific HTTP errors on the API as errorneous successes like this:
A good practice is to even catch all crashes in the code and convert them to a “success” result -> as statusCode: 500 and put the callstack or the stringified exception in the body of the response.
@pmuens Well I am not sure how to deal with the https://serverless.com/framework/docs/providers/aws/events/apigateway#status-codes section. I don’t know if it is still relevant (
lambda
method maybe) or not.Basically what I would add to the section is to return standard
callback(null, { statusCode: 403, body: "Forbidden", headers: { "Content-Type": "text/plain" } });
for defaultlambda-proxy
method.Then for
lambda
method use the existing document but I’m not sure if it should be present at all - it’s big and it would be better to put it somewhere else since it is documenting non-recommended method.