app.use(function (req, res, next) {
throw new Error('critical');
})
makes Express server to catch a critical error and output it, while I want it to crash.
Adding an error handler doesn't replace the default handler.
How can Express error handling be disabled for critical errors?
If you want your server to crash in the event of a critical error, you can define an error-handling middleware. This is done by defining a function with 4 parameters, the first being the error. This will be called when an error is thrown. You can check the error and determine if it's critical, and if so, call process.exit.
const app = require('express')()
app.use('/', (req, res) => {
throw new Error('critical')
})
app.use((err, req, res, next) => {
if (err.message === 'critical') {
process.exit(1)
} else {
// carry on listening
}
})
Related
I am currently working on node.js + express + mongoDB project. I am trying to handle error that occurs when data cannot be received from database. I am simulating this by terminating mongod process in console and calling .get in Postman. Sadly instead of getting an error in Postman I only get Unhandled Promise Rejection in console. I read a lot of posts about error handling and implemented it according to this guide: https://expressjs.com/en/guide/error-handling.html. I would be grateful for any idea of how can I fix this.
The code:
Printing all courses:
router.get("/", async (req, res, next) => {
try {
const courses = await Course.find().sort("dishName");
res.send(courses);
} catch (ex) {
next(ex);
}
});
error.js:
module.exports = function (err, res, req, next) {
res.status(500).send(`500 Error`);
};
index.js
const error = require(`./middleware/error`);
app.use(error);
app.use(error) is placed as the last app.use
There is a minor mistake in your code. The order of the req and res parameters in the error handler function should not be changed.
// Error.js
module.exports = function (err, req, res, next) {
res.status(500).send(`500 Error`);
};
I'm trying to setup an express app to catch any throw new error from a centeral function instead of many try and catch
var app = express();
tenantsRouter.get('/my_endpoint', async function(req, res, next) {
var result = await methodThatCouldFail()
res.status(HttpStatus.OK).json({result);
});
app.use(apiPrefix + '/tenants', tenantsRouter);
error_handler = function(err, req, res, next) {
console.error(`general error catcher - ${err}.`)
return res.status(HttpStatus.BAD_REQUEST).json({
'error': 'we are on it.'
})
}
// error handler
app.use(error_handler)
The thing is, unless I use specific try and catch in my_endpoint the error_handler doesn't catch throw new Error inside the methodThatCouldFail();
The only API that Express provides to pass errors down the chain of handlers is via the next() function. You need to wrap it around something that will do the try/catch and call next() for you:
function asyncHandler (f) {
return function (req, res, next) {
f(req, res, next).catch(next)
}
}
Now you can do:
tenantsRouter.get('/my_endpoint', asyncHandler(async function(req, res, next) {
var result = await methodThatCouldFail()
res.status(HttpStatus.OK).json({result);
}));
Which would work exactly how you expected it to work.
There are actually several implementations of this simple module on npm if you don't feel like writing it yourself including this one: https://www.npmjs.com/package/express-async-handler
Environment: node.js, Express, express-session package.
Background: I was testing an Express error handler and I got an error that I wasn't expecting.
The following simplified route throws an error.
TypeError: Cannot read property 'userValues' of undefined
exports.errorHandler = wrapAsync(async function(error, req, res, next) {
let loggedIn = req.session.userValues ? true : false;
res.render('error', { loggedIn });
});
However when I remove the error parameter it works without an error as I had anticipated.
exports.errorHandler = wrapAsync(async function(req, res, next) {
let loggedIn = req.session.userValues ? true : false;
res.render('error', { loggedIn });
});
Why might this be?
The basic pattern in the second example works in several dozen routes that don't include the error parameter.
You could use something like this. And it will only get executed whenever there is an ERROR 500 unless you passed the ERROR 404 to this one using next() function, if you handled all the errors correctly you should be able to make an ERROR 500 and this should be able to catch that ERROR.
const errorHandler = require("./your-file");
...
... every other route even error 404 handler
...
app.use(errorHandler);
What do I mean by using next() for ERROR 404
If you have used express-generator then you should already have this piece of code:
// catch 404 and forward to error handle
app.use((req, res, next) => {
next('not found');
});
The end file should looks something like this now if you use this approach:
...
... all previous routes
...
// catch 404 and forward to error handle
app.use((req, res, next) => {
next('not found');
});
// handle all other error
app.use(errorHandler);
Hope this helps
app.get('/test', (req, res, next) => {
const err = new Error('Test');
next(err);
});
express will log the error and stacktrace to the console. Is there a way that I can suppress the logging?
If you put an error handler middleware in your Express implementation to handle the next(err) call like this:
// defined as the last route
app.use(function (err, req, res, next) {
res.status(500).send('Something broke!')
});
then, Express won't log any error and you can control what response is sent for the error.
I'd suggest reading this page on Express error handling: https://expressjs.com/en/guide/error-handling.html.
If you look in the express code where this logging comes from, it comes from this code:
function logerror(err) {
/* istanbul ignore next */
if (this.get('env') !== 'test') console.error(err.stack || err.toString());
}
which curiously enough shows that if you do this:
app.set('env', 'test');
or you set NODE_ENV=test in the environment before launching your server, then it will skip the error logging too. But, it's much better to just control things with your own error handler as I show about where you can also control what type of response is sent.
In the following node.js server code, since "ABCDE" is not a defined a variable, error is thrown when '/upload' is requested. What confused me is that, the error stack trace printed on the console at server side is sent back to the client, which is unsafe.
How can I prevent that, other than catch that error?
var express = require('express');
var app = express();
app.use(function (err, req, res, next) {
res.send(500, 'Something broke!');
});
app.post('/upload', function (req, res) {
console.log(ABCDE);
});
app.listen(3000);
You already have the answer in your question. You need error-handling middleware (app.use a function with an arity of 4) to handle the error.
You just need to add the error-handling middleware after the router. Your example puts the the error handler above the the router.
Either move the app.use(function (err, req, res, next)) to the bottom of your code or insert
app.use(app.router);
above the error handler.
Refer to the documentation for more information about error handlers.