CodeGenieApp / CodeGenieApp/serverless-express
UnhandledPromiseRejection after sending response sometimes results in 502 error
- Dominant language
- JavaScript
- Stars
- 5.3k
- Forks
- 676
- PR merge metrics
- No merged PRs in 30d
Description
### Description
I think there exists a timing problem between sending the HTTP response passed to express and promise rejections happening afterwards.
See this pseudo code:
```
app.get('/', async (req, res) => {
const promise1 = Promise.reject({promise: 1});
const promise2 = Promise.reject({promise: 2});
let result;
try {
result = await promise1;
} catch (e) {
console.error(e);
return res.status(400).end();
}
try {
return res
.status(200)
.json(await promise2)
.end();
} catch (e) {
console.error(e);
return res.status(400).end();
}
}
);
```
I have an AWS Lambda behind an AWS API Gateway with a similar structure (my promises fetch HTTP resources).
When the request handler returns before the second promise is handled there will be an `UnhandledPromiseRejection`. Apparently `UnhandledPromiseRejection`s terminate the AWS Lambda execution (see https://forums.aws.amazon.com/message.jspa?messageID=906365).
On client side I sometimes get a 400 (--> my response) and sometimes a 502 (--> AWS response) status code.
With the workaround mentioned in the link above I always get the desired 400 response.
```
process.removeAllListeners('unhandledRejection');
process.on('unhandledRejection', (err) => console.error(err));
```
I don't know if the workaround is a good way to handle this situation but I think one solution or another should be part of this library. Of cause `UnhandledPromiseRejection`s should only be caught after a HTTP response was passed to express.
Contributor guide
Research direction
Start at the async app.get('/') handler and trace how serverless-express hands completed responses and later promise rejections to AWS Lambda and API Gateway. Reproduce the timing where promise2 rejects after the response path; done means the post-response behavior and resulting client status are defined without relying on a process-level unhandledRejection listener.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, express, javascript, node.js
- Domain
- api, backend, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100