Nodejs express app, propagate errors

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.

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);
    });
  };
};