7

According to Node.js documentation usually, it's not a good idea to use process.exit() because async IO operations like console.log() or other logging methods (Pino logging library in my case) might get skipped, the process exits before they complete their task. I was wondering what is the best way to handle errors inside a function. My final goal is to handle errors in a function and if the error is a fatal error then exit the process.

I wrote a simplified version of what I currently think is the best option (similar to the solution explained in Node.js docs):

const validateUserInput = (input) => {
  try {
    if (input === 'wrong') { throw new Error('sample error'); } // simplified
  } catch (err) {
    console.log('last message');
    // process.exit(1) --> using this might skip IO operation like the log on previous line
    process.exitCode = 1;
    return false;
  }
  return true;
};

if (validateUserInput('wrong')) {
  // rest of the code
}

// nothing should be written here
5
  • Just don't handle them with try/catch. Uncaught exceptions will exit (crash) the process by default, and IO that needs to complete (like logging libraries) will hook onto that to handle the crash gracefully. Commented Dec 29, 2021 at 17:20
  • joyent.com/node-js/production/design/errors is a good guide Commented Dec 29, 2021 at 17:24
  • @Bergi the problem is that I want to create proper messages for each message. Other than that I can throw an arbitrary error to achieve what you are saying. Then another problem is that it will print the error content in console and I don't know how to avoid that. This can be a solution if there is a way to avoid printing uncaught exceptions messages on console, but Idk if it's the best solution or not! Commented Dec 29, 2021 at 17:34
  • You can of course catch errors and rethrow a different one with a more appropriate message. But still, avoid process.exit :-) Commented Dec 29, 2021 at 17:36
  • "it will print the error content in console and I don't know how to avoid that" - you can use process.on('uncaughtException') for that. (Same for unhandled promise rejections). Your logging library might even do that for you, see its documentation (getpino.io/#/docs/help?id=exit-logging) Commented Dec 29, 2021 at 17:38

2 Answers 2

2

SIGTERM is the signal that tells a process to gracefully terminate. It is the signal that's sent from process managers like upstart or supervisord and many others.

You can send this signal from inside the program, in another function: read more

process.kill(process.pid, 'SIGTERM')

You can also setup your own listeners for this event, and perform other tasks.

process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Shutting down the application ...')
  })
})

But SIGTERM is not supported on windows, so you can use SIGINT instead, here is a useful info about SIGINT

After the SIGINT signal is received, the Node.js server initiates a shutdown sequence and enters shutdown mode. All of the existing requests are completed and no new requests are entertained. When the last request completes, the server closes all of the connections and shuts down. read more

Mor about processes here

Sign up to request clarification or add additional context in comments.

2 Comments

Updated both quotes with their source links.
The problem with this approach is that the code that comes right after process.kill still gets called. I have also tried process.emit.
0

If a fatal error occurs, the application will need to be terminated gracefully to prevent default behavior from happening and allow additional statements to execute first. You can achieve this by creating a simple event listener:

// For app termination
const gracefulShutdown = (msg, callback) => {
    server.close(() => {
        //execute additional code here
        console.log(`Application disconnected through ${msg}`);
        callback();
    })
}

process.on('SIGINT', () => {
    //execute additional code here
    gracefulShutdown('app termination', () => {
        process.exitCode = 1;
    })
})

4 Comments

Thanks for the answer, but I don't understand how this is the answer to my question!
@Amir...I'm sorry this isn't helpful. I was going by "My final goal is to handle errors in a function and if the error is a fatal error then exit the process" in your question. What were you looking for?
My problem is that I want to write proper logs (like not showing stack trace) before exit. If I call the process.exit() then the log might get missed, because it's async. If I don't call process.exit() then I need to handle the rest of the code, so nothing else gets executed. I don't think SIGINT help with anything here.
@server-unknown I think the OP already knows how to distinguish non-fatal from fatal errors. The question is explicitly only about fatal errors. You might want to drop the first half of your answer, everything before "If a fatal error occurs, …".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.