a field guide to resurrected wordsentry № 007

heisenbug

/ ˈhaɪ·zən·bʌɡ /
noun · from physicist Heisenberg + bug — “the bug that hides when watched”

A defect that changes or vanishes the moment you try to observe it. The looking is the intervention.

meet the bug
exhibits

The Bug

it crashes when no one is looking. it has an alibi for every crash you didn't see.
CANNOT
REPRODUCE
misbehavior
unobserved. misbehaving freely.
crashes (unwatched): 0 · times observed: 0reproduced under observation: 0

Move your cursor — the debugger's lens follows it. Off the bug, the creature scuttles and crashes, flinging errors into the margin. Bring the lens over it and the crashing stops dead: orderly, correct, blameless. Watch closely and it drifts away from the centre of your attention, because the act of looking is itself an intervention — the printf you added, the breakpoint you set, the slower clock. You will catch it behaving. You will never catch it misbehaving.

unwitnessed crashes
0
panel status · cannot reproduce
incriminating log · grows while it behaves
$ tail -f /var/log/it.was.working — waiting for a crash you won't see…

Lifeline of the Word

the jargon file
Hackers name it for a physicist, as a joke that stuck.

By the 1980s the term is in the Jargon File: a heisenbug is a bug that disappears or changes when you try to study it, punning on Werner Heisenberg. The name endured because every programmer had already met the thing and lacked a word equal to the betrayal.

1927
Heisenberg: to observe a system is to disturb it.

The uncertainty principle says some pairs of properties cannot both be pinned down — and at the limit, measurement itself perturbs what is measured. The pun is exact. A debugger is a measuring instrument, and the act of measuring a program changes the program's behaviour.

the mechanism
A printf adds a delay that hides the very race it was hunting.

Attach a debugger and timing shifts. Add a log line and a thread that used to lose a race now wins it. Compile with optimizations off and uninitialised memory reads differently. The instrument you brought to see the bug is the instrument that makes it hide. Observation is not free.

race conditions
The classic heisenbug is a matter of microseconds.

Two threads, an unprotected variable, an interleaving that only happens one time in ten thousand — until you slow one thread down to watch, and then it never happens at all. Concurrency is where heisenbugs breed, because concurrency is exactly where timing is the behaviour.

the bestiary
It has cousins: Bohr, Mandel, Schrödin.

A Bohrbug is solid and reproducible, the good kind. A mandelbug is so chaotic it looks intentional. A schrödinbug works fine until someone reads the code, realises it never should have, and then it breaks for everyone. Programmers built a whole zoology because one word was not enough.

observer effect
Profilers and tracers change the thing they report.

Instrumentation has weight. A profiler that samples every millisecond reshapes the schedule it is trying to describe; verbose tracing in production smooths the spikes you deployed it to catch. Testing folklore and physics arrive at the same caution: looking is an intervention.

now
Flaky tests, prod-only bugs, the green build that lied.

It only fails in CI. It only fails at scale. It passed a thousand times locally and falls over the moment no one is attached. Distributed tracing made some heisenbugs catchable and minted brand-new ones in the gaps between services. The oldest joke in debugging is still, quietly, on us.