Don't just check errors, handle them gracefully (2016)

44 anttiharju 42 6/3/2025, 6:49:33 PM dave.cheney.net ↗

Comments (42)

avg_dev · 23h ago
https://go.dev/blog/go1.13-errors

I wouldn't use the advice in this article. It's quite old and the stdlib now has support for new stuff via error wrapping.

vel0city · 23h ago
Gotta love reading a new to you codebase and seeing a bunch of

    catch (Exception ex) { };
littered throughout. Fixed the bug boss, close that ticket!
marklubi · 22h ago
Totally agree with finding the source of the bug (there are some that I've spent weeks tracking down, there are millions of people that have my fixed code on their devices).

If you've going to catch an error with a noop, there better be a comment explaining why you're not doing anything. It's not often, but sometimes, failing gracefully is just swallowing the error and moving on.

xboxnolifes · 22h ago
At minimum, the error should be logged somewhere, and not just vanished. At least you get to know how frequently it occurs if/when that becomes meaningful to you.
marklubi · 5h ago
In an app, if you have a string of network requests to your own services, there's no particular point in logging multiple (or any) 'no internet connection' errors. They won't make it to you, and having those doesn't provide much value. That's an end user problem.

I have plenty of monitors to ensure my services are available (four-nines uptime for almost a decade). Internet unavailable errors are useless to log.

vel0city · 21h ago
Exactly this. Log it, maybe at some really verbose log level, but please let me know it is hitting this point and a little bit of information of what the exception was.

Also, only do it for exceptions you think might actually hit there and you're OK with quietly squashing. Otherwise, please let something else try and handle it.

lapetitejort · 22h ago
I struggled with this recently. Someone was trying to patch up an error and force the program to continue. I asked him what was causing the error and he could only respond with how they were trying to patch it. I got so frustrated that I took on the error myself and fixed it with two lines of code.

I think the problem is that some people think errors are supposed to happen. Just a cost of doing business. They can't be fixed, only mitigated.

sidewndr46 · 21h ago
On Error Resume Next

The single line that magically fixes all Visual Basic 6 applications bugs

layer8 · 21h ago
Bash does it even by default. ;)
tshaddox · 22h ago
Sometimes you're stuck using some API that throws exceptions for expected (i.e. non-exceptional) errors, and you really do want to do nothing additional when those expected errors occur.
devman0 · 21h ago
This is, in theory, the difference between checked and unchecked exceptions in languages that support such distinctions. Checked exceptions are basically part of the control flow and the API contract used for things that can happen but are not necessary programmer errors (IO Exceptions being the classic example). Whereas unchecked exceptions are supposed to be used for programming errors (think Illegal Arguments, Null Pointer, Array Index Out of Bounds). Unchecked also usually cover other fatal conditions like stack overflow or OOM. Checked, handle with care, Unchecked, let the stack unwind and fail fast.
vel0city · 21h ago
Sure, I agree. I'd still prefer you properly scope it to just those expected exceptions, maybe put in some kind of debug level log related to it. The above code grabs every kind of exception and silently squashes it into oblivion.
Groxx · 22h ago
especially Exception. Ugh. Gotta love those interrupt-ignorers.
layer8 · 21h ago
Unfortunately, it’s somewhat of a lost cause unless you control all the code. Even some OJDBC drivers swallow interrupts. I had to resort to application-specific interrupt flags.
eknkc · 21h ago
Having a lint rule to disallow empty catch bodies has been a good practice for me. Sometimes you deliberately do it and even then I am forced to at least leave a `// ignore` there.
vel0city · 1h ago
Absolutely, linter rules that expose such things are critical to fixing these things. And I add them to the PR linter to comment on PRs when I can to point out discussions about such things.
atoav · 22h ago
Handling exceptions is interesting because in my experience a lot of it boils down to a social dimension:

* if the input data field for a telephone number contains a country name do you communicate that error back to the source, if yes how and how often (assuming your source isn't a life user bit a bureaucratic institution)

* if there is an error that really shouldn't happen, how will you notice? You probably don't have all the logs scrolling on 100 displays to watch for the red. So maybe send emails? But if you send emails about pointless stuff people will start to ignore them

scrame · 22h ago
this completely happened to me, but with a comment:

// this never happens

... guess what happened?

/happenings

layer8 · 21h ago
In every project I have an unchecked CantPossiblyHappenException type (usually with a better name ;)) that is thrown in such cases. This documents that the developer thought this condition can’t occur, while still escalating it should it nevertheless occur.
anttiharju · 23h ago
Posted this because of the other Go error handling post today https://news.ycombinator.com/item?id=44171677

I like error wrapping. I've worked in codebases where systems had to be debugged by piecing together individual log lines. With error wrapping I can usually see the exact path that lead to the error in one line.

glenjamin · 23h ago
It would be cool if someone could come up with a way for the runtime system to automatically wrap errors with the calling context.

That way you’d be able to trace the stack of functions that were involved in passing an error back up to the place where it’s actually handled.

Sarkie · 23h ago
It's a bold idea cotton
__s · 22h ago
It's possible, stdlib just doesn't do it

https://pkg.go.dev/github.com/pkg/errors

elcritch · 22h ago
It's sarcasm I believe, they used to call this exceptions. ;)
danesparza · 23h ago
"With error wrapping I can usually see the exact path that lead to the error in one line"

This is called a stack trace, and I agree it can be very useful (if the developers were thoughtful about their error handling)

eschatology · 23h ago
Stack trace is much more verbose and shows the symbols leading to the failing function call The error wrapping(s) produce a log line containing a brief message from each layer in the codebase that expected no errors — subtle difference but one is a dump and the other is much more meaningful.
kubanczyk · 22h ago
> The error wrapping(s) produce a log line containing a brief message from each layer in the codebase that expected no errors — subtle difference

Agreed. How I articulate it, often a function is just another layer, does one core thing and one-two extras. I wrap meticulously the errors of the extras. The core errors mainly speak for themselves, so they rarely need any wrapping.

Avoids:

    cannot load config:  cannot load config: cannot load config: file not found
But promotes:

    cannot load config: cannot connect to Configurer: loading client cert: PEM invalid
The latter case reads like a list of plot twists, because it is one. A corresponding 40-line stack trace might be less readable.
anttiharju · 23h ago
I suppose I phrased this poorly. Stack traces are useful indeed. I guess what I like that usually wrapped errors are bit more thoughtful, stack traces can look a bit like "vomit".
RSHEPP · 22h ago
from my experience of late, engineers usually toss stack traces into LLMs and ask what the issue is. good error wrapping, engineers grep for one of the first errors and get to the error code right away. both ways work.
sfn42 · 21h ago
If you can't read a stack trace without an LLM you're not an engineer.
Entwickler · 21h ago
Yeah, this has some general high level good advice, but is so old it doesn't include the new idiomatic ways of using errors.Is and error wrapping for error checking...
datadrivenangel · 23h ago
Software should fall over quickly. Graceful error handling can hide many issues.
markwaldron · 23h ago
My take on this post is that things will break, but they should tell you they broke in an actionable and somewhat standardized way. If the only message that shows up is "An error has occured" that doesn't help the user, especially if they are non-technical.
pixelpoet · 23h ago
I like my Go proverbs to be at least 100 years old: https://en.wikipedia.org/wiki/Go_proverb
rollulus · 22h ago
This was a great article back then but Go’s errors package has changed since then quite a bit, with e.g. Is, As, and fmt.Errorf’s %w.
3cats-in-a-coat · 23h ago
"Handling errors gracefully" doesn't happen at the handler. It starts at the execution model and your architecture. If a component can "bomb" in an isolated way, then the client that invoked that component can handle that gracefully.

This means things like durability, consistency, atomicity, and isolated side-effects (if any).

This is what Erlang does. A process is isolated, so when it just falls apart, the parent can handle that "gracefully" despite said process literally disintegrated in a critical irreparable way.

It's a bit like designing covert spy networks...

neuroelectron · 22h ago
Best way to handle errors is to exit
ninetyninenine · 23h ago
I love the go philosophy of errors being silent by default. It forces us developers to handle things gracefully. Additionally no stack traces along with the errors which is good because devs are too reliant on stack traces nowadays.
altruios · 22h ago
This sounds like it needs an /s.

The complaint of developers "being reliant on stack traces" tone sounds an awful lot like: "real programmers just use punch cards and ignore any tooling we've come up with in the last 70 years: just use your brain"

ninetyninenine · 20h ago
It’s not sarcasm. This is just my personal philosophy. I feel attacked.
827a · 22h ago
For a language that prides itself on its error handling, that's a whole lot of words written on the myriad of incorrect and bad ways to handle errors in the language, many of which are actively and irreversibly deployed in the standard library.
carlio · 23h ago
"Something went wrong. Please try again".