1

I am wonder if there is a best practice for propagating internal server errors back to the user. I.E. not the actual error (I log that server side), but at least a 500 and a message.

I currently have:

  app.use(function(err, req, res, next) {
    console.error(err.stack);
    res.send(500, 'Internal server error, please contact server administrator.');
  });

Which is great except that if an error is thrown my server crashes (expected).

So I am currently propagating any and all errors back to the express route, ie.

  app.get('/api/users', function (req, res, next) {
    User.getUsers(function (err, users) { // err comes back in function
      // dont throw err here in callback
      // throw err;

      // Instead call next with the error to let express now something bad happened
      if (err) return next(err);

      res.json(users);
    });
  });

This works great except that I have 30 routes that have the same line of code.

  if (err) return next(err);

Not a huge deal, but make me wonder if there is a 'better' way.

Thanks.

lostintranslation
  • 23,756
  • 50
  • 159
  • 262
  • What do you think about using [Domains](http://nodejs.org/api/domain.html)? Maybe it would help you. – gustavohenke Jul 04 '13 at 16:46
  • I think you may be right. I have not found to docs to be super clear w/ respect to domains. Or least have not seen a good example of how to use them in a big application with lots of routes. – lostintranslation Jul 04 '13 at 19:02

1 Answers1

1

EDIT: The OP wants to avoid propagating the error back to the express route.

Since node.js 0.6.x, you can use domains, which behave like a local process.on('uncaughtException, …)`. There are already several questions covering that, like Unable to handle exception with node.js domains using express.

The trick is to attach a separate domain to each request:

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

  var reqDomain = domain.create();
  reqDomain.add(req);
  reqDomain.add(res);
  reqDomain.on('error', function(err) {
    console.log("Req Domain Error: " + err);
    res.send(500, err.message);
  });

  next();
});

Whenever an exception occur, the domain error handled is called and you still have access to the response object to send a 5XX code.

However, as the doc states, you should always terminate your node.js process quickly after cleaning up your current connections when this happens.

Another thing to consider is that you need to make sure you stay in the same domain. I use this whenever I call an external module:

exports.preserveDomain = function (fun) {
  var d = process.domain;

  return function () {
    var args = arguments;

    d.run(function () {
      fun.apply(null, args);
    });
  };
};
Community
  • 1
  • 1
Laurent Perrin
  • 14,671
  • 5
  • 50
  • 49
  • That works, but I guess I confused the question. You still need to always propagate the error back to the route handler and do something with it. Not sure there is any way around that. Also not sure I want to expose server side error messages to clients. Would rather just give them 500 back. – lostintranslation Jul 04 '13 at 16:38
  • There is a rather dangerous way using domains. I'll update my answer. – Laurent Perrin Jul 05 '13 at 12:21
  • Nodejs 4.0.0 has deprecated the use of Domains – rohit12sh Sep 11 '15 at 21:08
  • To be accurate, it's not deprecated yet, but it will be as soon as they find a replacement. Right now, domains are still the best way to track errors like these. – Laurent Perrin Sep 17 '15 at 17:11