parse-server: Server exits with code 7 on uncaught exception before our handler is called

New Issue Checklist

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

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 20 (18 by maintainers)

Commits related to this issue

Most upvoted comments

This is more or less what I was aiming for - I agree that uncaught exceptions should not be silenced and that the server should exit to avoid continuing on a corrupt state, however, this should be an option for developers to handle themselves.

I think we could add such an option that disables the built-in handler. Do you want to open a PR for this? @dblythy What do you think?