Live data from Hacker News

Error Handling in Node.js

joyent.com

21–30 of 96 posts

Re: Error Handling in Node.js

#21

Some of this looks like horrible advice, particularly the defeatist attitude towards what the article calls "programmer errors". Statements to the effect that you can never anticipate or handle a logic error sensibly so the only thing you should ever do is crash immediately are hard to take seriously in 2016. What about auto-saving recovery data first? Logging diagnostic information? Restarting essential services in…

What about auto-saving recovering data?

It really depends upon the language and environment used. I work with C (almost legacy code at this point), and if the program generates a segfault, there is no way to safely store any data (for all I know, it could have been trying to auto-save recovery data when it happened). About the best I can hope for is that it shows itself during testing but hey, things slip into production (last time that happened in an asynchronous, event driven C program, the programmer maintaining the code violated an unstated assumption by the initial developer (who was no longer with the company) and program go boom in production). At that point, the program is automatically restarted, and I get to pour through a core dump to figure out the problem.

I'm not a fan of defensive programming as it can hide an obvious bug for a long time (I consider it a Good Thing that the program crashed otherwise we might have gone months, or even years, with noticing the actual bug).

Logging is an art. Too little, and it's hard to diagnose. Too much and it's hard to slog through. There's also the possibility that you don't log the right information. I've had to go back and amend logging statements when something didn't parse right (okay, what are our customers sending us now? Oh nice! The logs don't show the data that didn't parse---the things you don't think about when coding).

And then there are the monumental screw-ups that no one foresaw the consequences of. Again, at work, we receive messages on service S, which transforms and forwards the request to service T, which queries service E. T also sends continuous queries (a fixed query we aren't charged for [1]) to E to make sure it's up. Someone, somewhere, removed the fixed query from E. When the fixed query to E returned "not found," the code in T was written in such a way that failed to distinguish "not found" with "timedout" (because that fixed query should never have been deleted, right?) and thus, T shut down (because it had nothing to query), which in turn shut down S (because it had nothing to send the data to), which in turn meant many people were called ...

Then there was the routing error which caused our network traffic to be three times higher than expected and misrouted UDP replies ...

Error handling and reporting is hard. Maybe not cache invalidation and naming things hard, but hard none-the-less.

[1] Enterprise system here.

Re: Error Handling in Node.js

#22
post #8

My non-node specific suggestions: 1 - Don't catch errors unless you can actually handle them (and chances are, you can't handle them). Let them bubble up to a global handler, where you can have centralized logging. There's a fairly old discussion with Anders Hejlsberg that talks about this in the context of Java's miserable checked exception that I recommend [1]. This is also why, in my mind, Go gets it wrong. 2 - In…

> Only log actionable items

Easy to say but much harder to implement. For example, if you communicate with another service, a few network errors are usually not actionable and you'd have some fallback mechanism in you code. But tons of network errors (e.g. > 20%) is a problem that needs to be fixed now. So would you log the network error or not?

Re: Error Handling in Node.js

#23
post #8

My non-node specific suggestions: 1 - Don't catch errors unless you can actually handle them (and chances are, you can't handle them). Let them bubble up to a global handler, where you can have centralized logging. There's a fairly old discussion with Anders Hejlsberg that talks about this in the context of Java's miserable checked exception that I recommend [1]. This is also why, in my mind, Go gets it wrong. 2 - In…

When it comes to 1.), a better way to state things is may be that you shouldn't ignore errors unless you were able to completely handle them. Catching exceptions to throw exceptions with better messages is something I would stronly suggest, since almost no exceptions are useful without contextual information. I.e. which file was not found? The config, not the input or output. Things like this. This is especially usef…

Catching exceptions to throw exceptions with better messages is something I would stronly suggest

Also not every user in the world understand English.

I catch exceptions in two levels. One is the user initiated action. I seldom see this specified, but it seems obvious to me: if the user decides to do X, either X is done or a clear and meaningful message is shown, explaining what and why could not be done.

There is another finer grained location to do what you say (collecting details), logging and then re-raising up to the other level.

Swallowing errors is evil and no, not limited to C code.

Re: Error Handling in Node.js

#24
post #8

My non-node specific suggestions: 1 - Don't catch errors unless you can actually handle them (and chances are, you can't handle them). Let them bubble up to a global handler, where you can have centralized logging. There's a fairly old discussion with Anders Hejlsberg that talks about this in the context of Java's miserable checked exception that I recommend [1]. This is also why, in my mind, Go gets it wrong. 2 - In…

For point nr 4, at our company we tracked how many bugs that were fixed, came back afterwards (project with 80 developers for more than a decade old code base). We saw it's very rare that the same bug (after the fix) will pop up twice, and therefore decided not to add or write regression tests on them, and focus our testing efforts where it mattered more.

Re: Error Handling in Node.js

#25
For me, error handling has a major flaw: stack unwinding - extremely annoying thing to happen when the program state took many many hours to achieve. I don't think there is any language other than CL that allows restarts etc. to be defined; slime-repl too is invaluable when debugging.

http://www.gigamonkeys.com/book/beyond-exception-handling-co...

Re: Error Handling in Node.js

#26
post #8

My non-node specific suggestions: 1 - Don't catch errors unless you can actually handle them (and chances are, you can't handle them). Let them bubble up to a global handler, where you can have centralized logging. There's a fairly old discussion with Anders Hejlsberg that talks about this in the context of Java's miserable checked exception that I recommend [1]. This is also why, in my mind, Go gets it wrong. 2 - In…

For point nr 4, at our company we tracked how many bugs that were fixed, came back afterwards (project with 80 developers for more than a decade old code base). We saw it's very rare that the same bug (after the fix) will pop up twice, and therefore decided not to add or write regression tests on them, and focus our testing efforts where it mattered more.

It depends on what kind of error it is. If it is an off by one error, there isn't much you can do to test it, but if it is an input edge case you didn't handle correctly, then a test make a lot of sense, if for nothing else to verify the fix.

Re: Error Handling in Node.js

#27
post #19

I'm not really sure how to phrase this constructively, but this is horrible. Not the article, just the fact that humans expose themselves to this sort of stuff. Why would you choose to use a language that makes something as mundane as error handling this ridiculous and unpleasant?

There is nothing mundane about error handling, in fact it's one of the hardest things to get right in a programming language (see Rust's error handling saga for instance).

There is no language I know of where error handling is both simple and not overbearing.

Re: Error Handling in Node.js

#28

This isn't stuff every programmer should know, it only concerns people who are trying to write complex non-blocking Javascript without async/await (which are already implemented in Babel and proposed for ES7). It also focuses on Node-only idioms which IMHO should be deprecated in favor of ES6 Promises (which Node's LTS release supports natively!)

if you're not writing complex non-blocking Javascript in 2016, what are you even doing with your life? /s

Re: Error Handling in Node.js

#29
post #23

Earlier quoted context omitted.

When it comes to 1.), a better way to state things is may be that you shouldn't ignore errors unless you were able to completely handle them. Catching exceptions to throw exceptions with better messages is something I would stronly suggest, since almost no exceptions are useful without contextual information. I.e. which file was not found? The config, not the input or output. Things like this. This is especially usef…

Catching exceptions to throw exceptions with better messages is something I would stronly suggest Also not every user in the world understand English. I catch exceptions in two levels. One is the user initiated action. I seldom see this specified, but it seems obvious to me: if the user decides to do X, either X is done or a clear and meaningful message is shown, explaining what and why could not be done. There is an…

Interesting point. I have to confess that I've never seen logging done usable in a i18n sense. Of course, for UI applications, you're absolutely right.

When it comes to logging details, you have a point. But I still think a clear final error message is something to aspire to - especally if you're writing very busy and potentially multithreaded (or - even worse - async) services.

On this note, filtering logs according to thread IDs can be very helpful here. I wonder if that is also easily possible with "fibers".

> Swallowing errors is evil and no, not limited to C code.

Of course, nothing ever is - it's just where I've seen this thing the most (highly anecdotal evidence, I know :-) ). Unfortunately, the nature of many C APIs also makes it very non-obvious if you're skipping through the code, whereas an empty catch statement stands out somewhat.

Re: Error Handling in Node.js

#30
post #6

Earlier quoted context omitted.

Part of the problem in JS is that there's pretty much 2 classes of functions. Asynchronous functions and synchronous functions. Both are extremely common. Async/await solves this to some extent, because you can just go back to 1 way of error handling, which is throwing and catching exceptions. The third way (working with EventEmitter) is an odd pattern, but it's really more for specialized use-cases. Wouldn't really…

The trouble with "go foo()" is that it's fire-and-forget; foo's return value is literally discarded. When you need to know what happened (which should be nearly always), foo and every caller all have to opt-in to passing any result and/or error and/or panic value over a channel or something. It's one of many places where Go gives you tiny pieces of the right thing and makes you assemble them yourself.

Either that or you wrap it up in function that makes a channel, calls the function with it, then waits on that channel for the return value. Basically you can go back/forth between async and sync(ish) in go much more easily than in JavaScript.

In saying that though, if you have to do it a lot it probably means some of those functions should have been synchronous in the first place.

Post reply on HN