REST API Error Handling with Express.js

When you are writing an API, especially when is going to go public, you want the error responses to be as consistent as possible. You want your errors to be identical everywhere, to provide not too much information for your internal system but enough information to the debugger.

I am a REST fan and I hope you are too. What basically REST tell us, is to use HTTP's error codes for our API responses. E.g. when the user requests a particular row from our DB, using an identifier, and that row doesn't exists we should respond with a 404 Not Found status code.

Express.js has a default error handler. Basicaly it's just a middleware, with an extra argument, the err argument.

On an Express.js request lifecycle, when an error occurs, we pass on to the next middleware with populated error variable, and the error handler triggers.

Let's start with that.

router.use(function (err, req, res, next) {
	/* We log the error internaly */
    logger.error(err);

	/*
     * Remove Error's `stack` property. We don't want
     * users to see this at the production env
     */
    if (req.app.get('env') !== 'development') {
        delete err.stack;
    }

	/* Finaly respond to the request */
    res.status(err.statusCode || 500).json(err);
});

Two are the most essential parts here. Logging the error and proper displaying it. So I am logging it using a logger module and passing it to the user, using the error's status code. I have predefined those status codes so I don't have to deal with them every time. How? Let's see.

An error often consists of more than just an error code. We need a title, little more information and the stack trace on development environment. Instead of dealing with those information every time we create objects and only changing the bits we want each time. Here's a Not Found error object.

module.exports = function notFound(message, errorCode) {

  Error.captureStackTrace(this, this.constructor);

  this.name = this.constructor.name;
  this.message = message || 'The requested resource couldn\'t be found';
  this.statusCode = 404;
  this.errorCode = errorCode || 404;
};

We are inheriting the Node.js Error class and create a generic Not Found error object we can use every time we need one.

So now we need to pass this to the Express.js error handler. So on an ordinary controller we do:

app.use('/customers/:id', function(req, res, next){

	var id = properSanitization(req.params.id);

	someDBDriver.findOne(id, function(model){
    	if(!model) {
        	next(new NotFound('Entity with id: ' + id + ' couldn\'t be bound.');
        } else {
        	/* ... */
        }
    });
});

So now the error handler will take place and do it's magic.

Often, in a more complex API will need more expressive status codes to express it's disfunctionalities. In that case, you can still respond with the proper status code but keep an internal error eode that makes sense on your application. So, in case a user tries to login with wrong credentials, send a 401 to the API consumer but keep an internal code, e.g. 4001 that means "Wrong Username/Password". And that's what the errorCode is.

Here's a simple error collection i've wrote, to save you the hassle. Use it and send me your suggestions and/or notices.

Comments

Read Next

References from my Javascript 101
1 May 2015
I am Kostas Bariotis, a web developer, a proud wanderer and a passionate doer. My mission is to write clean and efficient code, to solve problems on the Web and to learn something more. Read more about me or get in touch .