Note: All my examples are in typescript and there are million other ways to achieve similar result, this is just my way of doing things.
If you are looking to start a new application in express, go over to the express site, use express-generator to create an application.
By default, any errors that are thrown within your application, will be sent as a 500 response code, along with the error stack trace in the body. This was inconvenient for me since,
- I don't want the end-user to know the system stack trace.
- I want to use exceptions for errors like
So, i decided to tweak the default behaviour and take control of error handling. If your use case is similar, then proceed with further steps.
Custom error handler
Create your own custom ErrorHandler class (
error_handler.ts), this will extend the node's Error class.
Now in your application you can invoke this custom error handler by calling,
Wiring error interceptor into express application
Once you start throwing exceptions within your application, next step is to convert those errors into a meaningful response for the end-user. Express app provides a way to hook up a custom error handler into your application. A middleware that takes in 4 parameters is your way to add your custom error handler.
Let's add the custom error handler function in the same
error_handler.ts class and export. This generic function will parse the thrown error and constructs appropriate response.
Now, whenever any error that is thrown in the application will be caught by this error handler. This will in turn respond back with appropriate status code.
Dealing with unknown errors
As you can see, the
customErrorHandler has a limitation of handling only the errors that are of type
AppError since it expects
statusCode to be present in the error.
However, there will be
RuntimeExceptions that will occur in the application. It's kind of hard to catch all these sort of errors in the application and re-throw them as custom errors.
So, we will improve our
customErrorHandler to handle such
Now, we introduced one more way of handling errors. If the caught error is not that of ours (
AppError) then we respond back with a 500 response.
We don't want our end user to know about the system internals and hence respond with a static message.
Dealing with asynchronous routes
This centralized error handling will not work for the errors that are thrown in the
await methods i.e, any error that are thrown in an async block will not reach our
This is a limitation with respect to express 4.x.
As a workaround, you have to make the routes to be synchronous. Instead of changing all the routes to synchronous blocks i used this
middleware to achieve a similar effect. Post wrapping my routes with this middleware, all the errors in async block will then reach our
Here is the gist to the final