Due to the unopinionated nature of JavaScript, there are many ways to accomplish a single task. This can be a double edge sword, especially when working in a larger team setting. This is where processes and guidelines come into play. In this article I’m going to show you how my team does error handling in an Express.js application using an error handling middleware.
Prerequisites
- Node.js installed on your machine
- Knowledge of Node.js and Express.js
- Knowledge of how middleware works in Express.js
Project Setup
Let’s create a basic Express.js application with one endpoint. The endpoint is a POST
method that takes two input parameters, title
and author
.
We check if title
and author
exist, if not we throw a 400 error and send back a JSON with status and message.
If title
and author
exist, the app will still crash because db
is not defined and our try/catch block will catch it and send back a 500 error and JSON with status and message.
Over time, as your endpoints and validations grow organically, typing out res.status(4xx).json({ some: JSON })
every time can get cumbersome quickly and also create a lot of code redundancy. Wouldn’t it be nice to do something like throw new BadRequest('message')
? Let’s see how we can accomplish that.
Create errors utils
Now let’s start by creating a utility function we can use to throw errors. Create a new folder /utils
and file errors.js
.
This file defines what errors we can throw in our application. The GeneralError
class extends Error
and is used to get our message and status codes.
Here, we have a BadRequest
and NotFound
class that extends GeneralError
. We also specify their error codes inside the getCode
block of GeneralError
.
For the simplicity of this demo, we will only haveBadRequest
, and NotFound
. If you want to add other error types, all you need to do a create a new class that extends GeneralError
and update its status code inside the getCode
block.
Create error handling middleware
Now we focus on implementing the express middleware to handle errors in our application. Create a new file /middleware/handleErrors.js
.
Note: The error handling middleware takes 4 arguments (error as the first arg) as opposed to 3 arguments for regular middleware.
The handleErrors
middleware function checks if the error passed in is an instance of GeneralError
. If it is, we return the status code and JSON body with status and message.
Using our error handling middleware
Let’s update our application and the endpoint to use our newly created error handling middleware.
Note: The error handling middleware should be placed last among other middleware and routes in order for it to function properly.
First, we import handleErrors
and register it as a middleware — as seen on line 25.
We also import BadReqest
and update line 16 to throw a new BadRequest
if title
and author
is missing.
Lastly, we add next
as the third argument to our route handler. Then we update the catch
block to pass errors into next
so our error handler can handle it.
Testing our custom error handling middleware
Let’s start our application and use Postman to see our error handling middleware in action.
First we make a POST request with no body. We get back a 400 error with a status and message as JSON.
Now, let’s make another POST request and pass in title
and author
. This time we get a 500 error with status and message as JSON.
And there we have it! A simple and clean solution for handling errors in an Express.js application.
Summary
In this article, we covered how to create an error handling middleware for an Express.js application. This will allow you to keep your code clean with less redundant code. All we need to do is throw the error and pass in a message. With this setup, it offers you the flexibility to add in more error classes for your application as needed.