I am working on a nodejs project and I had a major doubt/problem in nodejs error handling.
Whenever there is an exception caused by one of the request will the node stop the execution or will callback not returned of existing request, if so is there any way I can make the node to stop or throw exception after all the current request is completed.
I also wanted to ask if it is good to use domain as it is deprecated.
Related
Might be an idiotic question, but I was wondering why does, i.e. invoking Express' res.send() (a subclass of NodeJS' http.ServerResponse) more than once per a single request shut down a NodeJS server? Why doesn't it end the request while sending the first response and simply log the error, without crashing?
Express is just throwing an exception, then node handles it :
The 'uncaughtException' event is emitted when an uncaught JavaScript exception bubbles all the way back to the event loop. By default, Node.js handles such exceptions by printing the stack trace to stderr and exiting. doc
If you want to do something else, implement your own process.on('uncaughtException', (err) => {})
Or you could let it crash and use stuff like forever to bring it back up.
Using node.js, when I run the program
setTimeout(() => console.log("Timed out"), 0);
console.log("finishing");
I see
finishing
Timed out
But when I add a throw before "finishing"
setTimeout(() => console.log("Timed out"), 0);
throw new Error();
console.log("finishing");
I see
throw new Error();
^
Error
at Object.<anonymous> ...(stack trace here)...
And I don't see any mention of "Timed out".
Why is that? Even though the initial context would throw, once the stack was freed up, I expected the callback I passed to setTimeout would still run.
Does having an uncaught exception cause all timeouts to get canceled? Is this feature documented somewhere?
If I have multiple timeouts, is there a way for me to make sure that all the other timeouts continue to run when they can even if one of them happens to throw?
Unlike a web application running on browser, a Node application runs as a process on top of Google V8 JavaScript Engine. If you look into https://nodejs.org/api/timers.html is states that
The timer functions within Node.js implement a similar API as the timers API provided by Web Browsers but use a different internal implementation that is built around the Node.js Event Loop.
As the above statement explains, even though the same global functions are available in both cases, their implementations are different. Therefore when an uncaught exception occurs in a Node application, all code related to timeouts will stop as the process is terminated. The best way to handle this is to properly handle all exceptions. You can use the below code to capture all uncaught exceptions from the process level itself.
process.on('uncaughtException', function(error) {
console.log(error);
});
I am using node.js with domains and cluster to catch unexpected exceptions (programmer bugs) then restart gracefully. However we occasionally have programmers failing to add the final .catch().finally() to make sure that their code actually returns.
I can easily add a timeout that will throw an exception after a pre-specified time to make sure that these bad requests will not live forever. But what I'd like to do is to have the timeout pull information out of the domain to explain what had happened in the request so that we can have a log/notification/whatever that starts with a good indication of where the programmer bug was.
Is there any reasonable way to do that?
In case it matters, we are using express as a framework, express-domain-middleware to get domains/restart logic, and promises for async logic.
You don't actually need domains for this. If you use a promise library (like bluebird, or when, or even Q) or a recent version of Node (Namely, io.js) you don't have to remember using .catch on all chains and use the dedicated events:
process.on("unhandledRejection", function(e, reason){
// promise was rejected, even if no `catch` or `finally` attached
// restart the process
});
Note that domains are deprecated and will likely be removed in a future version of NodeJS, if you're using promises you already have catch safety so there's that.
I'm trying to find the best place to handle connectivity errors, or any other global errors that crash the server.
What is the right place to catch adapter/global errors and not have them crash the server?
Specifically, I want to handle these types of errors in a graceful way:
Error spawning mySQL connection:
error: Hook failed to load: orm (Error: connect ECONNREFUSED)
error: Error encountered while loading Sails core!
error: Error: connect ECONNREFUSED
from the sails docs: http://sailsjs.org/#!documentation/config.500
thats the error handling sails exposes from within the config
if your error passes that, you can hook in there, otherwise you can hook in node's process
process.on('uncaughtException', function (err) {
if (err.toString() === 'Error spawning mySQL connection') {
//rende some error page
}
})
if the exception thrown is async the only way to catch it is trough process
do note however, that these kinds of errors are almost always unrecoverable, so crashing (and restarting) is the best approach
most modules loaded use local variables and expose only a subset of their internals trough module.exports, unloading a module and restarting its local code can be done, but you would need to unload all dependant modules and all modules holding references to it also. Thats why the normal approach is to let it crash
I am working with a partner on a project. He has written a lot of code in Node.js+Express, but we've been running into issues with the architecture.
To remedy this, my primary role has been to figure out the best way to architect a Node.js+Express application. I've run into two scenarios, dealing with errors, and I'd like some suggestions.
First, how do I capture top-level exceptions? The last thing I want is for a bug to completely kill the node process. I want to continue serving users in the face of any error.
Secondly, some errors are passed back via callbacks (we're using caolan / async). As part of each route handler, either we render a view (GET), redirect to another route (POST) and we want to redirect to an error screen with a custom error message. How can I make sure to capture this logic in one place?
First, how do I capture top-level exceptions? The last thing I want is for a bug to completely kill the node process. I want to continue serving users in the face of any error.
Edit: I think node's philosophy in general is that any uncaught exceptions should kill the process, and that you should run your node app under some kind of process monitor with appropriate logging facilities. The following advice is regarding any other errors you might encounter in your express route handlers etc.
Express has a general errorHandler, which should capture all thrown errors as well as everything passed as a parameter to next in your routes/middlewares, and respond with 500 Internal Server Error.
Secondly, some errors are passed back via callbacks (we're using caolan / async). As part of each route handler, either we render a view (GET), redirect to another route (POST) and we want to redirect to an error screen with a custom error message. How can I make sure to capture this logic in one place?
You could create a custom handleError, which you call in each callback like so:
async.series(..., function(err, results) {
if(err)
return handleError(req, res, err);
// ...
});
Or you could just pass the errors on with next(err) and implement your custom error handler as described here: http://expressjs.com/guide/error-handling.html
Top level exceptions:
You can use the uncaughtException event from process, but it's generally not recommended.
Often applications will go into a corrupted state (eg. you have some state which typically gets set, but the exception caused that not to happen) when an exception is thrown. Then, it will just cause more and more errors from there on onwards.
A recommended approach is to use something like forever to automatically restart the app in case it crashes. This way you will have the application in a sane state even after a crash.
Error handling in express:
You can create a new Error instance and pass it to the next callback in the chain.
Eg.
express.get('/some/url', function(req, res, next) {
//something here
if(error) {
next(new Error('blah blah'));
}
});
To handle the error from here on onwards, you can set an error handler. See express docs on error handling
Checkout the excellent log-handling module Winston: https://github.com/flatiron/winston
It allows you to configure exception handling in a manner that will not only log it, but will allow the process to continue. And, since these would obviously be serious issues, you can even configure Winston to send out emails on specific event types (like exceptions).