I am Hack Sparrow
Captain of the Internets.

Express.js Custom Error Pages – 404 and 500

Express does a good job of handling 404 and 500 errors by default. However, many a times, the error is page is now what we would like it to look like. Is there a way to customize it? Yes there is.

Online, you will come across many ways of implementing custom error pages for Express, but a lot of them do not use the correct approach, and those who do, do not explain properly how to do it, or what is going on. In this post I will show you how to create custom 404 and 500 error pages the right way, and explain how and why it works.

If you are asking this question, I will assume that you already have a working Express application and you are familiar with the application code, at least somewhat. I will also assume that you created the skeleton of your app using the express command (if you did not, start using it - type express -h at the command line).

To get some context, open app.js and find these lines:

  ...
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
...

In the first line, we have added the router middleware, which makes defining routes in Express possible.

In the second line, we are adding Stylus to pre-process our CSS files.

In the third line, we are setting up our static directory for serving CSS, JavaScript, images etc.

You may come across some suggestions like the following to handle 404 errors:

app.get('*', function(req, res) ...

This approach is wrong, it is using a route to handle 404 error. Because the router middleware is added before the static middleware, it will intercept the requests for static file like CSS, JavaScript etc. You could make it work somehow, but it would a dirty hack job, we need to use the right approach, so abandon this method.

So what's the right method?

We need to create two middleware to handle 404 and 500 errors. Add these two right below app.use(express.static(path.join(__dirname, 'public')));:

  // Handle 404
app.use(function(req, res) {
    res.send('404: Page not Found', 404);
});

// Handle 500
app.use(function(error, req, res, next) {
    res.send('500: Internal Server Error', 500);
});

Try loading a non-existent page on your website now or generate an error by calling an undefined function in one of your route handlers. You will see your custom error pages now.

Hey, but aren't we looking to create cool looking custom error pages?

Ah yes! Go ahead create these two files in the views directory.

File: 404.jade

extends layout
block content
h1= title
p Dude, where is my page?
a(href='/') Take me to the homepage!

File: 500.jade

extends layout
block content
h1= title
p #{title}
p #{error}

Now, update the error handling middleware.

  // Handle 404
app.use(function(req, res) {
    res.status(400);
    res.render('404.jade', {title: '404: File Not Found'});
});

// Handle 500
app.use(function(error, req, res, next) {
    res.status(500);
    res.render('500.jade', {title:'500: Internal Server Error', error: error});
});

An important point to note is that, these two middleware must go at the very end of the Express middleware stack, else you will get unexpected results. Also, the 500 error handling middleware has an arity of 4, if you define it with anything lesser, it will fall back on the default Express 500 error handler.

Now restart you app, load the error-prone pages, and get ready to admire your witty looking, customized 404 and 500 error pages.

7 Responses to “Express.js Custom Error Pages – 404 and 500”

  1. Arun says:

    Thanks for sharing. It helped me understand things better :)

  2. Shaun says:

    Just wanted to say thanks! Been looking around on stackoverflow all morning and couldn’t find exactly the right way to intercept the 404. Your suggestion for the 2 arity function at the end of the middleware was perfect. The other ways kept intercepting my static files.

    I’m going to share this on my blog as well and link back to your page on it. Thanks again!

  3. MxLandry says:

    Thanks for that post. I searched a good way to set the status and have a custom page and it’s exactly what I found here.

  4. Ludovic says:

    Thanks a lot ! :)

  5. Ted Husted says:

    Perfect! Much needed!

  6. ravi says:

    Thanks very much!! helps a lot!!

  7. Murthy says:

    Thank you so much… it helped and I undetstood error handling a lot better now….. thanks once again

Make a Comment