Bug-to-Error Distance

Kristian Dupont
2 min readMay 21, 2024

I hadn’t articulated this before, but I recently realized that I have an internal metric for assessing bugs and errors.

Photo by Nuno Antunes on Unsplash

In this context, a bug is a piece of code that doesn’t do what the programmer intended, and an error is an undesired outcome or behavior.

Now, I am deliberately being vague about what distance refers to, as it’s a bit of a combination. It can mean “in the code”, measured in lines, files, folders, or services. It can also mean “in time”, where the visible error might appear significantly later than when the bug in question was triggered.

For syntax errors, this distance is practically zero. A squiggly line appears right underneath the bug. The error is both co-located and immediate, at least if you are working in a syntax-highlighting editor.

On the other hand, if you have a service that accidentally inserts garbage into your database, you might not discover it for a long time. The distance can be severe, both in terms of code location and time. This sort of bug is significantly harder to track down and fix.

So, it seems valuable to assess code not only on how potentially error-prone a pattern or piece of code is, but also on what the potential bug-to-error distance is, and try to minimize it.

How does one do that in practical terms? For instance, it has affected my view on type inference. For a while, my perspective was: infer all the things! Type safety without the plumbing code, best of both worlds — surely, that’s the way to go, always? Well, specifying types is like creating little valves in the code. “At this point, this is what I expect things to look like”. If you don’t do this, you will have less plumbing code but the price you pay is an increased bug-to-error distance because a piece of data may have a different shape than you expected, inferred from something “far away”.
I now tend to enable the explicit-module-boundary-types linter rule when writing Typescript, which forces explicitly typed signatures for exported functions. I am sure there are plenty of other similar considerations that I haven’t thought of yet.