The solution to "Error handling"...

Dennis dkorpel at gmail.com
Fri Jul 3 23:08:26 UTC 2026


...is testing your software. 😉

There's no shortage of interesting discussions about Error vs. 
Exception, throwing vs returning, floating point NaN, UTF 
replacement chars, or the 'correct' error handling mechanism in 
general.

The CPU doesn't care about any of this, it just executes 
instructions to move memory around. The user doesn't care about 
any of this either, they just want a program that gets the job 
done. Your task as a programmer is to generate the CPU 
instructions that do the job the user wants as best as you can. 
If you find an abstraction that helps handling errors, then use 
it by all means. But beware that premature abstractions always 
get things wrong. It's easier to write straightforward code first 
and see which repetitive patterns naturally emerge from that.

The other day my X11 desktop application failed to create a 
graphics context, and as a result it printed a crappy error 
message and crashed. But wait, I thought I was meticulously 
checking the return values of al my `glx` calls and returning 
gracefully? Turns out that before returning the `null` context, 
X11 calls a default error callback that prints something to the 
console and aborts. To fix the bad UX, I set `XSetErrorHandler` 
to my own callback and printed a better error message instead.

AHA! X11 has a C interface, so this is all the fault of C's lack 
of good error handling language features. If only they used 
Exceptions, right? Well, the browser version of my app (running 
on top of Javascript APIs) also likes to randomly error, for 
example when the CDN provides and old cached .wasm module instead 
of the new one. The result: a flooded browser console (which  is 
hidden by default), while the page stays blank and unresponsive.

If you catch an Exception and simply show the message in a GUI, 
the error is usually unhelpful. A recent one I got from Phobos 
was "Positive Conversion Overflow". Without attaching more 
information to Exceptions in intermediate catch blocks, the error 
is devoid of context. (Unless you print the stack trace but it's 
not like a regular user can make any sense of that)

But wait, I heard Exceptions are also considered bad these days, 
the current trendy thing is returning `Result<Value, Error>` 
types, like Rust does. I don't have that much Rust experience, 
but I have seen code full of `result.expect("quick message")` 
(which panics and aborts the program on error) to satisfy the 
compiler's type checks, with the idea "it's a quick script, I 
can't be bothered to do proper error handling for this". So you 
get extra boilerplate in the code, but the UX is no better than a 
C library with an error callback that prints and aborts, like X11.

My personal takeaway is that regardless of what language features 
you use for error handling, you rarely get it right first try. 
You have to *test your software* by triggering  error conditions 
and observing what the UX of that is. Then it becomes immediately 
obvious where the error should have been handled and what 
information should be attached. With concrete feedback, fixing 
your code becomes so much easier.

Of course, when you have hundreds of error conditions, this 
becomes rather tedious. This is where [Walter is completely 
right](https://forum.dlang.org/post/10utksm$1h2t$1@digitalmars.com) that the best 'error handling' is *no handling*.

In [The Easiest Way To Handle Errors Is To Not Have 
Them](https://www.dgtlgrove.com/p/the-easiest-way-to-handle-errors), Ryan Fleury gives concrete C examples, but the principles apply to other languages as well. I haven't read Walter's book recommendation "A Philosophy of Software Design" yet, and if you haven't either, maybe that post is more accessible.



More information about the Digitalmars-d mailing list