santiagoIT
santiagoIT

Reputation: 9421

Express 3 error middleware not being called

I am trying to setup error handling for my express app and running into the following problem.

I defined an error middleware and add it as the last middleware:

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

    console.log('JUST TESTING. ERROR HANLDER HAS BEEN CALLED...');
    next(err);
});

Now I would expect this middleware to be called whenever an error occurs:

app.get('/datenschutz', function(req, res, next){
        return next(new Error('Just testing')); // handle everything here
    });

However my middleware is never called! The browser does display the stack trace however. This seems that there is another middleware that is catching this error and processing it before I can do anything about it.

The problem is that I have no clue where this middleware could be defined, as I have a very simple setup:

// setup ssl for local testing
var
    app = express();

app.
    use(express.static(__dirname + '/public')).
    use(express.bodyParser()).
    use(express.cookieParser());

Why is my error handling middleware not being called? Where is this 'default' error handling taking place?

Thanks!

* EDIT * I see that the middleware is indeed working. However this is the case if I call it from another middleware function. However it is not being invoked if the error occurs inside a function defined as an express route (GET, POST, etc..). This is very strange. If I add my error middleware to the route callbacks it then works:

app.get('/testError', function(req, res, next){
        return next(new Error('Just testing')); // handle everything here
    }, function(err,req,res,next) {
        console.log('This error handler is called!!');
        return next();
    });

* EDIT 2 - FOUND ACCEPTABLE WORKAROUND ** I am surprised it has to be done this way. As I had read many entries/questions about error handling in express and never found this possibility mentioned. However it seems that if an error ocurrs inside a route callback regular error middleware handlers will not pick it up. You will need to define an error handler at route level.

app.all('*', function(err,req,res,next) {
        console.log('This is a global error handler at route level....');
        return next(err);
    });

Upvotes: 19

Views: 6197

Answers (4)

Amr Abdalrahman Ahmed
Amr Abdalrahman Ahmed

Reputation: 1010

instead of making

app.get('/datenschutz', function(req, res, next){
        return next(new Error('Just testing')); // handle everything here
    });

you can install express-async-errors

and just make

app.get('/datenschutz', function(req, res){
       throw new Error('Just testing');
    });

it works as expected

Upvotes: 0

skeller88
skeller88

Reputation: 4504

Updated answer for Express 4 users from the Express 4 docs. See example from docs below. Note that app.router is deprecated and no longer used. I also added a dummy route to make the ordering clear:

"You define error-handling middleware last, after other app.use() and routes calls; For example:

var bodyParser = require('body-parser');

app.use(bodyParser());
app.get('/', function(req, res) {
    res.send('hello world');
})
app.use(function(err, req, res, next) {
  // logic
});

"

Upvotes: 3

amnah
amnah

Reputation: 131

I had this problem as well, but I couldn't figure out why it wasn't working even though I set my error handler after the app.user(app.router). As it turns out, I already had an error handler that I wasn't aware of.

Specifically, if you use the express cli to generate an app like I did, it will automatically add in this in:

if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

Unfortunately for me, I added a bit more middleware to my app, which consequently obscured this statement and thus prevented my custom error handler from being called.

Simply remove that and then it should work properly.

On a side note, I should mention that the original solution still worked - even with the app.use(express.errorHandler()).

app.all('*', function(err,req,res,next) {
    console.log('This is a global error handler at route level....');
    return next(err);
});

Upvotes: 3

Oren
Oren

Reputation: 1006

EDIT 2 (sabtioagoIT) works. But just for those who missed it, emostar's solution also works. I understood to move the error handling 'use' call to the end, but there seems to be an easier option as emoster suggests, use app.router (before the error handling 'use' call).

Upvotes: 1

Related Questions