Description
New Issue Checklist
- I am not disclosing a vulnerability.
- I am not just asking a question.
- I have searched through existing issues.
- I can reproduce the issue with the latest version of Parse Server.
Issue Description
See previously closed issue which first pointed this out, but was closed due to clerical reasons.
When an error is thrown somewhere within our request handlers, if its uncaught, ParseServer catches it and re-throws. Unfortunately, this takes away any uncaught exception handling ability from our application code itself.
See this code snippet from src/ParseServer.js
if (!process.env.TESTING) {
//This causes tests to spew some useless warnings, so disable in test
/* istanbul ignore next */
process.on('uncaughtException', err => {
if (err.code === 'EADDRINUSE') {
// user-friendly message for this common error
process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
process.exit(0);
} else {
throw err; <-- this causes the server to crash
}
});
.
..
}
Node.js does allow registering multiple uncaught exception handlers, however, if you throw an error from within one of these handlers, it skips any other registered handlers and exits the application with code 7.
Steps to reproduce
We noticed this error when one of our express middlewares was setting a response header after it was returned to the client. You can reproduce this by making your own faulty middleware:
app.use((req, res, next)=> {
const originalEnd = res.end.bind(res) as typeof res.end;
res.end = (
...args: Parameters<typeof originalEnd>
): ReturnType<typeof originalEnd> => {
setTimeout(() => {
console.log('setting bad header in res.end');
res.header('X-Some-Header', 'x');
}, 100);
return originalEnd(...args);
};
next();
});
Actual Outcome
The server crashed with exit code 7.
Expected Outcome
The uncaught exception should be handled by ParseServer, or ignored and left to the application to manage.
Environment
v6.1.0-alpha.6
Server
- Parse Server version: v6.1.0-alpha.6
- Operating system: MacOS / Linux
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): Local and AWS ECS
Database
- System (MongoDB or Postgres): MongoDB
- Database version: 4.4
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): Local and MongoDB Atlas
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc): Irrelevant
- SDK version: Irrelevant
Logs
/Users/x/Documents/GitHub/synap/common/temp/node_modules//parse-server/lib/ParseServer.js:251
throw err;
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:399:5)
at ServerResponse.setHeader (node:_http_outgoing:663:11)
# printed by our on exit handler:
application exited with code 7