How to properly handle errors in Express?

35,531

Solution 1

You'll want to check out Express Error Handling. From there:

app.param('userId', function(req, res, next, id) {
    User.get(id, function(err, user) {
        if (err) return next(err);
        if (!user) return next(new Error('failed to find user'));
        req.user = user;
        next();
    });
});

The sweetspot that you are missing is the return next(...)

Solution 2

That's because you're doing it wrong: you already threw an Error (which will be processed by Express and return a 500 - Error page for the user or something like that) but you are also trying to send your own response to the client: res.send('event found!');

You should really check out the Express guide about Error Handling here: http://expressjs.com/guide/error-handling.html

What I would do in your example is:

function NotFound(msg){
  this.name = 'NotFound';
  Error.call(this, msg);
  Error.captureStackTrace(this, arguments.callee);
} 

app.get('/event/:id', function(req, res, next){
  if (req.params.id != 1) {
    throw new NotFound('Cannot find event ' + req.params.id);
  } else {
    res.send('event found!');
  }
});

app.error(function(err, req, res, next){
    if (err instanceof NotFound) {
        res.render('404.ejs');
    } else {
        next(err);
    }
});

Solution 3

You have a couple of problems in your code:

  • When responding to the client, you need to use the response object (res rather than req).

  • When sending an error to next, you should return, so the rest of the function doesn't run.

Here's your code after fixing those errors:

app.get('/event/:id', function(req, res, next) {
    if (req.params.id != 1) {
        return next(new Error('cannot find event ' + req.params.id));
    }

    res.send('event found!'); // use res.send (NOT req.send)
}); 
Share:
35,531
YWCA Hello
Author by

YWCA Hello

Updated on July 09, 2022

Comments

  • YWCA Hello
    YWCA Hello almost 2 years

    I am beginning to work with Express JS and have run into an issue. I can't seem to figure out the proper way to handle errors.

    For example, I have a web services API that serves an object called "event". I'd like to return a simple string of "cannot find event" when a user submits an event id that isn't found. Here is how I'm currently structuring my code:

    app.get('/event/:id', function(req, res, next) {
        if (req.params.id != 1) {
            next(new Error('cannot find event ' + req.params.id));
        }
    
        req.send('event found!');
    });
    

    When I submit an id other than 1, Node crashes with the following output:

    http.js:527
       throw new Error("Can't set headers after they are sent.");
             ^
    Error: Can't set headers after they are sent.
        at ServerResponse.<anonymous> (http.js:527:11)
        at ServerResponse.setHeader (/usr/local/kayak/node_modules/express/node_modules/connect/lib/patch.js:62:20)
        at /usr/local/kayak/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js:72:19
        at [object Object].<anonymous> (fs.js:107:5)
        at [object Object].emit (events.js:61:17)
        at afterRead (fs.js:878:12)
        at wrapper (fs.js:245:17)
    

    From what I can tell by using the node.js debugger, execution of the block of code continues after next() is called, meaning that req.send('event found!') tries to run. I don't want this to happen.

    The only workaround that I've found is to simply throw a new Error() instead of "next-ing" it, but this results in a default Express HTML error page being generated. I'd like a little more control than that.

    I have taken the time to read over the error handling section of the Express documentation, but I couldn't make sense of it.