I've read Joyent's stellar guide on error handling in node. I'm also familiar with using error middleware in Express to handle errors. However, there's one detail that continues to perplex me: how do you decide when to percolate up the error to the caller (e.g. with cb(err)
or throw new Error()
) vs. pass along to the error handler middleware (with next(err)
)?
I'll use the fetchConfig
example function in the Joyent article to illustrate my question. The pathway of the function is as follows:
- Load configuration
- Connect to the database server. This in turn will:
- Resolve the DNS hostname of the database server
- Make a TCP connection to the database server.
- Authenticate to the database server
- Make the DB request
- Decode the response
- Load the configuration
- Connect to the database server. This in turn will:
- Start handling requests
Let's assume there's an express error handler (the function(err, res, req, next) {}
pattern) that exists to log the error message and pass it along to the client.
(Still borrowing from the Joyent article...) Let's say the connection in 1.1.2
fails: myserver: Error: connect ECONNREFUSED
. In step 1.1.2
, if you handled the error in that module by calling next(err)
, you'd be logging a rather cryptic error message.
Instead, you first want the error to percolate through steps 1.1
and 1
, wrapping the error message as you go to produce a clearer error message: myserver: failed to start up: failed to load configuration: failed to connect to database server: failed to connect to 127.0.0.1 port 1234: connect ECONNREFUSED
To me, this indicates that the programmer must make a decision at every stage of the error to either a) wrap and pass the error to its caller, or b) pass the error to the express error handler. My question is centered on that decision: what guides the decision, how does one choose logically and consistently?
Thanks to any that may help.