6

I'm building an API (using Expressjs v4) and typically I've dealt with errors within the route rather than using middleware. For example:

router.use('/', function(req, res, next) {
  ...
  if (err)
    return res.status(500).send({type: "serverError", message: "Something has gone wrong on our end."});
}

I now realise that middleware is the "way to go." I've seen the rather limited documentation on the Expressjs site here: http://expressjs.com/guide/error-handling.html but still unsure of a few things.

I've added in the server.js:

function errorHandler(err, req, res, next) {

}

but how do I supposed to handle the different types of errors (400,404,500 etc)?

I'm finding myself writing 3 lines of code each time an error occurs:

//A route
var err = new Error();
err.status = 404;
return next(err);

and I can access the status using:

function errorHandler(err, req, res, next) {
  console.log(err.status);
  if(err.status == "400")
    //do something
  else
    //etc etc
}

Surely there's an easier way than this? Am I missing something?

2 Answers 2

4

Instead manually creating error, you can delegate that error like below.

return next(err);

And your error will go deep down all the routes defined until it find routes with below signature.

app.use(function (err, req, res, next) {

});

You can see the err argument in above route.

Ideally you can use below two methods for both DEVELOPMENT & PRODUCTION environment.

if (process.env.NODE_ENV === 'development') {
    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        logger.log('info', err.message + " expected URL was " + req.url);
        res.status(err.status).send(err.status, {
            message: err.message,
            error  : err
        });
    });
}

app.use(function (err, req, res, next) {
    res.status(err.status || 500);
    logger.log('error', err.message + " expected URL was " + req.url);
    res.status(err.status).send(err.status, {
        message: err.message,
        error  : {}
    });

});

You can capture actual populated error object in there.

Sign up to request clarification or add additional context in comments.

5 Comments

but the err won't have status though will it unless I manually set it as in my question right??? - and those three lines I'm trying to avoid because I will have to do this for every error.
Not every error comes with status. but you are using callbacks or aren't you !
Yeah I'm using callbacks
The thing is I need to create errors for things like MissingToken and TokenNotFound etc etc
If you want to set status code for every other error, you have to do it manually and delegate that error as per workflow i mentioned. We are using 500 status code for such errors.
3

You should create your own Error type that allows you to provide all the information necessary to act on the error.

var util = require('util');

function HttpError(message, statusCode){
    this.message = message;
    this.statusCode = statusCode;
    this.stack = (new Error()).stack;
}

util.inherits(Error, HttpError);
module.exports = HttpError;

Then include your new error object in your code and use it like

next(new HttpError('Not Found', 404));

Or you could go crazy and implement an error type for each response code pre-populating the statusCode part.

Ref: What's a good way to extend Error in JavaScript?

1 Comment

You can omit the this.stack part if you don't need the stack trace, but it's super helpful sometimes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.