Keep your routes error handlers simple and flexible for your nodejs/express app

Aleksey Alkhutov
Fusion Tech
Published in
3 min readFeb 10, 2020

Wow.. My first story. Well, let’s try)

Each of us thought how to make good error handling with logging, scalability and allow this system to be flexible. I gonna to share with you my thoughts how to do this and would like to talk what structure you might to stick in your nodejs apps.

So, here we go.

First of all let’s make pretty simple nodejs/express server with couple routes.

Good. Now let’s add couple controllers. One of them will just produce some response data, but another one will raise error.

If we run server and go to `localhost:3000/two` it fails like this

It can be easily intercept by adding one middleware

app.use((err, req, res, next) => {
res.json({ message: err.message });
});

Now we handle errors through all routes, but missed one thing: each error may have own status code.

Let’s add new route with :id param in path

app.get("/:id", (req, res) => {
const data = userCtrl(req.params.id);
res.json({ message: data.name });
});

userCtrl we will consider a bit later.

Now we are close to one of the ways to solve our main problem. Create file exceptions.js and put there this content

General idea is implementing custom error class based on Error and extend it with all necessary fields. You can add custom logging there as well.

Add new controller and emulate DB (just create simple object what will map ids with names). Now controllers.js looks like this

Here is time to play with all of it. Go to new route with id 1

And check this route for id 12 as well

Great. Now we can see error message what we expect. But status still 200. We need to update error middleware a bit:

app.use((err, req, res, next) => {
const { statusCode = 500 } = err;
res.status(statusCode).json({ message: err.message });
});

Here we check status code from err variable and if this is missing — set default status code 500 .

For our case we will receive 404 error. Cool!

Such error rising we can implement via another way: instead of passing Error object as throw param you can pass there simple object like this

throw { message: "Value param is broken", statusCode: 404 };

Handling of this error will be the same with previous way.

First way has two advantages:
1) full customizable
2) you can get trace of the error via processing err.stack field and get broken place of you code

Second way is pretty simple and doesn’t take a lot of code.

Thanks for the reading. Link to github you can find below. Bye!

--

--