At the very end of my server.js file I have the following code:
app.use(logErrors);
function logErrors (err: Error, req: Request, res: Response, next: NextFunction) {
console.log(err);
mongoDal.log(err.message, err);
next(err);
}
but this code doesn't get reached when an error occurs.
I also have the Node.js error handling function, which doesn't get reached either:
process.on('uncaughtException', function (err: Error) {
try {
console.log(err);
mongoDal.log(err.message, err);
} catch (err) {
}
});
This is the code that produces the error:
app.get('/test_feature', function (req: Request, res: Response) {
makeError();
res.send("Done");
});
function makeError(){
throw new Error("asdasdad");
}
BTW the error does get written into the console (but not by a function of mine), and the app doesn't crash.
What I'm trying to make is a generic solution that will catch every unhandled exception in one place.
What am I doing wrong?
Below is the short working example with handling for 3 types of errors:
1) passed to next()
handler,
2) throw-ed inside route handler,
3) unhandled error inside callback of some function called from route handler.
(1) and (2) are captured using custom error middleware handler (A) and (3) is captured by uncaughtException
handler (B).
Express has own error handler which outputs error if it gets the control using the chain of next()
calls (i.e. if there is no custom error handler or if it passes the control further using next(err, req, res, next)
). That's why you still getting an error message in console even if youyr handler is not triggers.
If you try to run the example for cases (1) and (2), you'll see the error outputs twice - by custom handler (A) and by default Express error handler.
'use strict';
var express = require('express');
var app = express();
var server = app.listen(8080, function() {
console.log('* Server listening at ' + server.address().address + ':' + server.address().port);
});
// Example 1: Pass error in route handler to next() handler
app.use('/1', function(req, res, next) {
console.log('* route 1');
next(new Error('* route 1 error'));
});
// Example 2: throw the error in route handler
app.use('/2', function(req, res, next) {
console.log('* route 2');
throw new Error('route 2 error');
});
// Example 3: unhandled error inside some callback function
app.use('/3', function(req, res, next) {
console.log('* route 3');
setTimeout(function(){
throw new Error('route 3 error');
}, 500);
});
// Error handler A: Express Error middleware
app.use(function(err, req, res, next) {
console.log('**************************');
console.log('* [Error middleware]: err:', err);
console.log('**************************');
next(err);
});
// Error handler B: Node's uncaughtException handler
process.on('uncaughtException', function (err) {
console.log('**************************');
console.log('* [process.on(uncaughtException)]: err:', err);
console.log('**************************');
});
Node version: v7.2.0
Typical error is to place error handlers before route definitions, but according to your description that's not the case.
To locate the issue you can try to reduce your own code to same size as mine and I think, the problem will become obvious.
UPDATE
Moreover, if I try to run the code you provided (with trivial modifications), it works for me:
'use strict';
var express = require('express');
var app = express();
var server = app.listen(8080, function() {
console.log('* Server listening at ' + server.address().address + ':' + server.address().port);
});
//process.on('uncaughtException', function (err: Error) {
process.on('uncaughtException', function (err) {
try {
console.log('*** uncaughtException:', err);
//mongoDal.log(err.message, err);
} catch (err) {
}
});
//app.get('/test_feature', function (req: Request, res: Response) {
app.get('/test_feature', function (req, res) {
makeError();
res.send("Done");
});
function makeError(){
throw new Error("asdasdad");
}
app.use(logErrors);
//function logErrors (err: Error, req: Request, res: Response, next: NextFunction) {
function logErrors (err, req, res, next) {
console.log('*** logErrors:', err);
//mongoDal.log(err.message, err);
next(err);
}
The result is (stack traces are truncated):
* Server listening at :::8080
*** logErrors: Error: asdasdad
at makeError (/home/alykoshin/sync/al-projects/dev/nmotw/400-express-error-handling/main-stackoverflow.js:32:9)
...........
Error: asdasdad
at makeError (/home/alykoshin/sync/al-projects/dev/nmotw/400-express-error-handling/main-stackoverflow.js:32:9)
...........
You may see at the beginning the ouput of logErrors
handler and then the output of default Express error handler.
Note: your error handler middleware MUST have 4 parameters: error, req, res, next. Otherwise your handler won't fire.
I was fighting this problem until I've discovered this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With