Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node, Express, domains, uncaught exceptions - still lost

I have been reading for hours on exception handling in Node. I understand the cons of using uncaughtException, I understand that shutting down the process is good for preventing any "unknown state" where "anything can happen". I understand that using domains is the way to go, and I understand how to properly implement domains, specifically Explicit Binding...

...but I'm still not getting any results for just basic error handling.

I would like to be able to just catch any uncaught exceptions for the purpose of logging. I don't mind killing the process or anything else deemed "undesirable". I just want a log.

I don't feel like I should have to wrap everything in a try/catch or use some library to emit errors... please correct me if I'm wrong and I will change my ways.

I am using Node and Express and I have the following simple code:

var express = require('express');
var domain = require('domain');

var serverDomain = domain.create();
serverDomain.on('error', function(err) {
    console.log("SERVER DOMAIN ERROR: " + err.message);
});

serverDomain.run(function() {
    var app = express();
    app.get('/testing', function() {
        app.nonExistent.call(); // this throws an error
    });

    var server = app.listen(8000, function() {
        console.log('Listening on port %d', server.address().port);
    });
});

The error shows up in the console, but the console never receives the "SERVER DOMAIN ERROR..." message. I have also tried wrapping the request/response in their own domain as well, to no avail. Even more disappointing is the fact that using the following does not work either:

process.on('uncaughtException', function(err) {
    console.log('uncaughtException caught the error');
});

Am I doing something wrong? Where do I go from here? How can I catch the above error?

like image 961
Ryan Wheale Avatar asked May 27 '14 06:05

Ryan Wheale


2 Answers

You can use connect-domain.

The problem is that the exception happens during Connect's routing, which has both a try/catch block around its execution, as well as a default error handler which prints out stack trace details when running in a non-production mode. Since the exception is handled inside of Express, it never reaches your outer layer for the domains to handle.

Here is an example why to use connect-domain package instead of domain.

http://masashi-k.blogspot.com/2012/12/express3-global-error-handling-domain.html

var express = require('express');
var connectDomain = require('connect-domain');

var app = express();
app.use(connectDomain());
app.get('/testing', function() {
    app.nonExistent.call(); // this throws an error
});

app.use(function(err, req, res, next) {
    res.end(err.message); // this catches the error!!
});

var server = app.listen(8000, function() {
    console.log('Listening on port %d', server.address().port);
});
like image 199
Waqas Ahmed Avatar answered Nov 09 '22 01:11

Waqas Ahmed


This happens because Express handles by itself the errors that may appear and in this way it simplifies your work. See Express Guide for error handling. You should use the structure below to handle the errors that may appear:

app.use(function(err, req, res, next){
    console.error(err.stack);
    res.send(500, 'Something broke!');
});
like image 5
micnic Avatar answered Nov 09 '22 02:11

micnic