0

I'm trying to setup a Global error handler in Express where I can catch all the errors and return a custom error message, but I also want to remove the try/catch from all endpoints, going from this:

app.get('/', (req, res, next) => {
    try {
      throw new Error('BROKEN')
    } catch (err) {
      next(err)
    }
})

to this:

app.get('/', (req, res, next) => {
   throw new Error('BROKEN')
})

I have already tried to add thy express error handler below. However, it only gets called if I first catch the error on the route and pass the error on next().

app.use((err, req, res, next) => {
  res.status(500).send('Something broke!')
})

I did reflect the code to have a function like catchAllError().

cons catchAllError = fn => (req, res, next) => {
  try {
    fn(req, res, next);
  } catch {
    next(err)
  }
}

bring the footprint of all the endpoints down to:

app.get('/', catchAllError((req, res, next) => {
   throw new Error('BROKEN')
}));

However now I want to remove the callback too.

I try to handle all global errors using

process.on('uncaughtException', (err) => {
   console.log('What to do with the error now!');
});

However, even tho I can catch all the errors here I have no longer access to the req/res/next.

Any ideas on where to go from here to get all the exceptions caught and return with a custom message to the user without the need to add try/catch on all endpoints?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Icaro
  • 14,585
  • 6
  • 60
  • 75
  • You can create your own method that will catch a synchronous exception as shown here: https://stackoverflow.com/questions/58536012/express-error-middleware-without-next/58537460#58537460. – jfriend00 Aug 05 '22 at 00:34
  • And, a version that also handles returned promises or rejected promises: https://stackoverflow.com/questions/61086833/async-await-in-express-middleware/61087195#61087195. – jfriend00 Aug 05 '22 at 00:36
  • Hi @jfriend00 thank you for your response, as I explain on the question I already implement that, I want to take one step forward now and remove it. – Icaro Aug 05 '22 at 00:41
  • 1
    I don't think you understand what these do. These allow you to make `app.getP()` that you can just use instead of `app.get()` and it will automatically have the try/catch and rejected promise error handling in it. This lets you eliminate using your own `try/catch` everywhere or `catchAllError()` everywhere. Just use `app.getP()` instead and it's all built-in. Your question does not show what these offer. – jfriend00 Aug 05 '22 at 00:51
  • Hey @jfriend00 yes I do understand that it does, and I think it would be good on a new project, however, I have a service endpoint with 100s of endpoints, would be hard to get that approved. That is why I want to see if I can catch all exceptions somehow at the same time I still have access to the res so I can send a custom error response – Icaro Aug 05 '22 at 01:26
  • 1
    "*[My error handler] only gets called if I first catch the error on the route and pass the error on `next()`.*" - that shouldn't be necessary. [Express does handle synchronous exceptions](http://expressjs.com/en/guide/error-handling.html) by itself just fine (and with Express 5, even those from `async` handlers). Are you sure the cases where you found `try`/`catch` to be necessary are actually synchronous? Please post a [mcve] with the code where your default error handler does not work. – Bergi Aug 05 '22 at 02:25
  • Also no, you can't (and shouldn't!) do this with a global `uncaughtException` event handler – Bergi Aug 05 '22 at 02:26
  • Well, no you can't catch all exceptions globally in a safe manner. You can register for `uncaughtException`, but at that point, the system is in an unknown state where resources may leak (like file handles or other system handles) because no proper error handling was done. There is NO magic substitute for writing proper error handling. Don't spend any time looking for it. Instead, spend that time writing proper error handling. – jfriend00 Aug 05 '22 at 02:50
  • @jfriend00 All the errors have been caught and handled appropriately. All I want to avoid is having to catch the error on a controller level, as all the errors that bubble up to the controller will be handled the same way. Why add try/catch blocks to all endpoints is all it will do is call next? All I want to do is to bubble it one level up and catch it there. – Icaro Aug 05 '22 at 04:00
  • @Icaro - Well, you can only call `next()` in the scope where `next` is defined. You cannot do that globally as `next()` is not available globally. You apparently know and understand the options available to you, but just don't want any of those. The universal place where `next()` is available is inside of the implementation of `app.get()` or whatever you use in its place (as suggested in one of the answers I linked). – jfriend00 Aug 05 '22 at 04:10

0 Answers0