Node.js official documentation - errors - nodejs.org
Error Handling in Node.js - www.joyent.com
Error
global object - developer.mozilla.org
try
...catch
- developer.mozilla.org
Checklist: Best Practices of Node.JS Error Handling (2018)
Give Stackman an error and he will give an array of stack frames with extremely detailed information for each frame in the stack trace.
With Stackman you get access to the actual source code and surrounding lines for where the error occurred, you get to know if it happened inside a 3rd party module, in Node.js or in your own code.
By Thomas Watson, dev at Elastic.
Project is backed by Elastic.
AriaMinaei/pretty-error - github.com
See node.js errors with less clutter
Error Handling in Node.js - www.joyent.com
Represent run-time problems experienced by correctly-written programs. These are not bugs in the program.
Problem with :
They are bugs. These are things that can always be avoided by changing the code.
They are not handled correctly because the developer have not implemented error handling properly, not because it is impossible.
Ex :
undefined
People use the term "errors" to talk about both operational and programmer errors, but they're really quite different.
This distinction is very important: operational errors are part of the normal operation of a program. Programmer errors are bugs.
Sometimes, you have both operational and programming errors as part of the same root problem because they can chain themselves.
Example a server crashes because it try to use undefined variable, then clients will get an operational error (can't connect it is crashed).
Similarly, failure to handle an operational error is itself a programmer error.
The distinction between operational errors and programmer errors is the foundation for figuring out how to deliver errors and how to handle them.
Any code that does anything which might possibly fail (opening a file, connecting to a server, forking a child process, and so on) has to consider what happens when that operation fails.
That includes knowing how it may fail (the failure mode) and what such a failure would indicate.
The key point here is that error handling has to be done in a fine-grained way because the impact and response depend on exactly what failed and why
You may end up handling the same error at several levels of the stack. This happens when lower levels can't do anything useful except propagate the error to their caller, which propagates the error to its caller, and so on.
Often, only the top-level caller knows what the appropriate response is, whether that's to retry the operation, report an error to the user, or something else.
For any given error, there are a few things you might do:
The best way to recover from programmer errors is to crash immediately.
You should run your programs using a restarter that will automatically restart the program in the event of a crash.
With a restarter in place, crashing is the fastest way to restore reliable service in the face of a transient programmer error.
The only downside to crashing on programmer errors is that connected clients may be temporarily disrupted, but remember :
The best way to debug these problems is to configure Node to dump core on an uncaught exception.
Finally, remember that a programmer error on a server just becomes an operational error on a client.
If you don't know what errors can happen or don't know what they mean, then your program cannot be correct except by accident.
The question is : How do you deliver errors to the code that called your function?
throw
delivers an error synchronously. If the caller (or someone else in the call stack) used a try
/ catch
then they catch the error. If none the program crashes (there is a particular case with domains and uncaughtException
event) callback(err, result)
, the historical pattern in node for asynchronous handling. The user passes the callback to your function. For him, err
or result
is null
, never both null
or valued. async
/ await
, since node 8, upgrade of asynchronous handling to look like synchronous. try
/ catch
by the caller is supported.EventEmitter
listening to error
event. To deal with streams. Function returns the EventEmitter
object. Caller listen to events.throw
, and when do you use callbacks or event emitters?It depends :
By far, the most common case is an operational error in an asynchronous function (see fs
module for examples).
The next most common case is an operational error in a synchronous function like JSON.parse
.
For these functions, if you encounter an operational error (like invalid user input), you have to deliver the error synchronously. You can either throw it (much more common) or return it.
For a given function, if any operational error can be delivered asynchronously, then all operational errors should be delivered asynchronously.
The general rule is that a function may deliver operational errors synchronously (e.g., by throw
ing) or asynchronously (by passing them to a callback or emitting error
on an EventEmitter
), but it should not do both.
This way, a user can handle errors by either handling them in the callback or using try
/catch
, but they never need to do both.
We've left out programmer errors. Recall that these are always bugs.
They can also usually be identified immediately by checking the types on arguments at the start of the function.
You should throw these errors immediately, since the program is broken. To do this, we recommend validating the types of all arguments at the start of the function.
How do you know what's a programmer error vs. an operational error? Quite simply: it's up to you to define and document what types your function will allow and how you'll try to interpret them.
If you get something other than what you've documented to accept, that's a programmer error.
You have to use your judgment to decide how strict you want to be.
Imagine a function called connect
that takes an IP address and a callback and invokes the callback asynchronously after either succeeding or failing.
Suppose the user passes something that's obviously not a valid IP address, like 'bob'
.
In this case, you have a few options:
'bob'
. This is strongly recommended.'bob'
, emit an asynchronous error indicating that you couldn't connect to IP address 'bob'
.Using assert
module to check function parameters.
If the assertion is wrong, node throws.
Assert based exceptions are unrecoverable at the JavaScript layer.
So it is an easy way to crash the app when it encounters a programmer error.
The better approach is to be super strict at the beginning and to be less strict in future versions without breaking what already exist.
If you do the opposite, super loose then going stricter, you will produce massives breaking changes to your users.
process.on('uncaughtException')
?Domains and the process-wide 'uncaughtException'
event are primarily useful to attempt to handle or recover from unanticipated programmer errors. For all the reasons described above, this is strongly discouraged.
name
s)Error
objects (or subclasses : RangeError
, ReferenceError
, SyntaxError
, TypeError
) for all errors, and implement the Error
contract (name
, message
and stack
props at least).name
property to distinguish errors programmatically (you don't need to subclass Error
for each error type).Error
object with properties that explain details