Skip to content

Server exits with code 7 on uncaught exception before our handler is called #8695

Closed
@omairvaiyani

Description

@omairvaiyani

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:breakingBreaking change requires major version increment and `BREAKING CHANGE` commit messagestate:releasedReleased as stable versionstate:released-alphaReleased as alpha versionstate:released-betaReleased as beta versiontype:questionSupport or code-level question

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions