Which is the better practice about Node.js Error Handler - node.js

To avoid node/ express server crashing, it is always a good idea to catch the errors. As far as I found, there are three ways to record the error:
throw new Error(err);
logger(err);
res,json(500, err);
Should I use all of them to catch an error, if so, what is the invoking order?
Is it possible to avoid crashing if we just throw the error?

Check out this guy link and learn about error handling
https://www.youtube.com/watch?v=p-2fzgfk9AA
His video is very informative and he explains all different types of error handlings

You can use a package connect-domain.
Here is the example.
http://masashi-k.blogspot.com/2012/12/express3-global-error-handling-domain.html
Or You can use node.js built in uncaught exception event to handle uncaught errors.
//put this code in your server.js
process.on('uncaughtException', function(err) {
console.log('Caught exception: ' + err);
});

Related

How to best make treat promise rejection like uncaught exception?

If there are unhandled Promise rejections, Node.js currently just logs an error, with a mention that in the future such errors will cause a process to exit.
I have two questions regarding this:
How to best make Node.js today treat unhandled Promise rejections such that it exits the process?
If the failure of some promise is, in effect, the same as an uncaught exception and should cause exiting the process, how to best make that happen?
There are obviously lots of ways to do this, but I am trying to find the cleanest and simplest way that would not require me to make a new utility library just for this functionality.
Some candidates:
process.on('unhandledRejection', (err) => { throw err; }) - might be confusing as nothing shows it is from a promise, instead of just a thrown exception, and also not usable in .catch().
process.on('unhandledRejection', (err) => { console.error(err); process.exit(1); })
In most of the cases you almost never want your node server to exit when there is an exception or error. The very job of error handler (try/catch and .catch()) is to make sure your server stay up and running even when there is an exception or error.
Rather, when you get an exception or error, you should:
catch that error and throw a custom error with a specific error message (and error code if that suits you).
catch the custom error at the end of promise chain (or app.use(err,...)) and send that error message to the user.
Following is a simple psudocode where the user is giving you XML and expects parsed JSON as a response:
function parseXML(xmlStr){
return someParsingLibrary.parseXml2JSON(xmlStr)
.catch(()=>{
throw new Error("Your xml was not valid");
})
}
app.post("/parse", function (req, res, next) {
let xmlStr = req.body.xml;
parseXML(xmlStr)
.then((json)=>{
res.status(200).send({description:"Success", body:json});
})
.catch((err)=>{
res.status(422).send({description:err.message, body:err});
})
});

Express: next(err) stacktrace

I find it difficult to find where the error occured when using next(err). Is there a way how to save the stack to trace the error back to the original files? (Even if it was a validation error I would like to know the exact place from where it originated.)
You can add error.stack to your error handling.
console.log(error, error.stack)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack

Get response for uncaught Exceptions using process.on

I am able to caught uncaught Exceptions in Node.js using
process.on('uncaughtException', function (exception, req, res) {
console.log("error======== >>>>>>>>> ",exception);
})
But i want to send an error message in the res.send({error:"Something broke"}) when my code goes in any exception rather than just halting it in time out.
I google it but could not find anything helpful.
i added process.exit(1) but it could not help.
It is not wise to continue operations after uncaughtException is hit. You should let the child die and spawn a fresh process to hand further requests.
More on this can be found here:
https://nodejs.org/api/process.html#process_warning_using_uncaughtexception_correctly

How do I handle all errors on my server, so that it never crashes?

Let's say I have this server route (using expressjs):
app.get('/cards', function(req, res) {
anUndefinedVariable // Server doesn't crash
dbClient.query('select * from cards', function(err, result) {
anUndefinedVariable // Server crashes
res.send(result.rows)
});
});
When I simply reference an undefined variable at the root of the /cards route callback, the server doesn't crash, but if I reference it in the nested callback it crashes.
Is it because Express is catching the error when it's at the root level? Why doesn't it also catch the errors in the nested functions?
I tried catching the error like this myself:
app.get('/cards', function(req, res) {
try {
dbClient.query('select * from cards', function(err, result) {
anUndefinedVariable
res.send(result.rows)
});
} catch (e) {
console.log('...')
}
});
But it never enters the catch block. Maybe this is the reason Express isn't able to catch the error. Is it because that, in order to be able to catch an error, you need to do it on the function that actually calls the callback? E.g. try {functionThatCallsTheQueryCallback() } catch(e) {...}? I don't think so, as query certainly calls the callback indirectly at a certain point.
How would I go about catching all errors so that my server never crashes?
try...catch only catches errors that occur in synchronous operations. It won't catch errors that occur in callbacks to async operations, like you have in your second example above.
As for the first example, express handles errors that are thrown synchronously and sends a 500 response to the client.
You can look into domains for handling errors across async operations. But be aware that they are pending deprecation. It's worth reading through the warnings in the docs about why they're being deprecated.
It can done in node, although generally not recommended, by letting node to handle the uncaughtException event,
https://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception
process.on('uncaughtException', (err) => {
console.log(`Caught exception: ${err}`);
});
Another more preferable approach would be just let it crush, and have it restarted automatically afterward. There are some tools available for this, such as nodemon, pm2, forever...

Nodejs exit on error, shoud prevent or not?

I'm using Nodejs in my windows machine. the question is Nodejs always terminate process on errors e.g. empty Mysql insert statement.
So in production time, and without manual error handling, how can prevent NodeJs exit?
example code:
app.post('/api/accounts',function(req,res){
pool.getConnection(function(error,connection){
connection.query('insert into accounts set ?',req.body,function(err,results){
if (err) {
throw err ;
} else {
console.log(results) ;
}
});
});
console.log('post received') ;
console.log(req.body);
});
Imagine i post an empty req.body.
nodejs will exit on error like this
\node_modules\mysql\lib\protocol\Parser.js:77
throw err; // Rethrow non-MySQL errors
^
Is it possible to configure something in node to just show errors but don't exit?
It's not really a good thing to be continuing execution after a unhandled exception has been thrown by the interpreter (as Ginden said in his answer) - anything could happen and it could prove to be a mistake later, any sort of hole could easily be opened by stopping the process from cleaning up after something went so unexpectedly wrong in your code.
You could sensibly add a event handler for unhandledException like the answer by Ginden points out, however, it seems you're using express and it would make much more sense actually handling the error with middleware when it happens, instead of using throw as per your code.
Replace throw err; with return next(err); and that should mean the request will fall through to the next set of middleware, which should then handle the error, do some logging, tell the user, whatever you want it to do.
app.use(function(err, req, res, next) {
// Maybe log the error for later reference?
// If this is development, maybe show the stack here in this response?
res.status(err.status || 500);
res.send({
'message': err.message
});
});
Don't try to prevent process shutdown. If error was thrown, anything could happen.
Warning: Using 'uncaughtException' correctly
Note that 'uncaughtException' is a crude mechanism for exception handling intended to be used only as a last resort. The event should not be used as an equivalent to On Error Resume Next. Unhandled exceptions inherently mean that an application is in an undefined state. Attempting to resume application code without properly recovering from the exception can cause additional unforeseen and unpredictable issues.
Exceptions thrown from within the event handler will not be caught. Instead the process will exit with a non zero exit code and the stack trace will be printed. This is to avoid infinite recursion.
Attempting to resume normally after an uncaught exception can be similar to pulling out of the power cord when upgrading a computer -- nine out of ten times nothing happens - but the 10th time, the system becomes corrupted.
Domain module: don't ignore errors.
By the very nature of how throw works in JavaScript, there is almost never any way to safely "pick up where you left off", without leaking references, or creating some other sort of undefined brittle state.
The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else.
The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker.

Resources