My use case sends a custom JSON error message since I use the express delivery function for my REST API. I think this is a fairly common scenario, so I will focus on this in my answer.
Short version:
Express error handling
Define middleware for error handling, such as other middleware, with the exception of four arguments instead of three, in particular with the signature (err, req, res, next) .... You define the middleware for error handling last after other applications app.use () and routes
app.use(function(err, req, res, next) { if (err instanceof JSONError) { res.status(err.status).json({ status: err.status, message: err.message }); } else { next(err); } });
Raise errors from anywhere in the code by doing:
var JSONError = require('./JSONError'); var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Long version
Canonical rollover method:
var err = new Error("Uh oh! Can't find something"); err.status = 404; next(err)
By default, Express handles this by carefully wrapping it as an HTTP response with code 404 and a body consisting of a message line attached to the stack trace.
This does not work for me when I use Express as a REST server, for example. I want the error to be sent as JSON, and not as HTML. I also definitely do not want my stack trace to be ported to my client.
I can send JSON as a response using req.json() , for example. something like req.json({ status: 404, message: 'Uh oh! Can't find something'}) . If desired, I can set the status code using req.status() . The combination of two:
req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});
It works like a charm. However, I find it rather cumbersome to print every time I have an error, and the code is no longer self-documenting, like our next(err) . This looks too similar to how a regular (i.e., valid) JSON response is sent. In addition, any errors caused by the canonical approach still lead to HTML output.
This is where the Express middleware appears. As part of my routes, I define:
app.use(function(err, req, res, next) { console.log('Someone tried to throw an error response'); });
I also subclass Error in a custom JSONError class:
JSONError = function (status, message) { Error.prototype.constructor.call(this, status + ': ' + message); this.status = status; this.message = message; }; JSONError.prototype = Object.create(Error); JSONError.prototype.constructor = JSONError;
Now that I want to clear the error in the code, I do:
var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Returning to the middleware for error handling, I change it to:
app.use(function(err, req, res, next) { if (err instanceof JSONError) { res.status(err.status).json({ status: err.status, message: err.message }); } else { next(err); } }
A subclass error in JSONError is important because I suspect that Express is checking the instanceof Error first parameter passed to next() to determine if a normal handler or an error handler should be called. I can remove the instanceof JSONError and make minor changes to ensure that unforeseen errors (like a crash) also return a JSON response.