A Heisenbug is a failure or behavior that changes when observation or interference changes the program. Multithreaded applications are especially vulnerable: pausing execution with a debugger can alter the timing and prevent the original problem from appearing. section 1.2.1 section 2.3
Treat the debugger as one investigative instrument, not as a neutral window into every failure. If stepping changes the symptom, compare observations made with logging, profiling, mocks, or stubs; reducing execution to one thread can sometimes make debugging practical. section 1.2.1 section 2.3
Ask these diagnostic questions:
- Does the failure occur only without the debugger, or only after stepping and pausing? section 1.2.1
- Could timing explain the change, such as an expiring access token, timer, or short-lived external session? section 2.3
- Would logs or a controlled stub preserve observations without changing execution as much? section 2.3 section 1.2.1
Multithreaded failure
A multithreaded application behaves incorrectly during normal execution, but appears correct when paused in a debugger. The pauses have changed thread timing, so the observed run no longer represents the original failure. Capture behavior with logging, consider profiling cautiously, or simplify the investigation by reducing active threads to one. section 1.2.1
Figure 1.6 A Heisenberg execution. In a multithreaded app, when a debugger interferes with the app’s execution, it might change how the app behaves. This change doesn’t allow you to correctly investigate the initial app behavior that you wanted to research.
Illustrates how debugger interference can change multithreaded execution and block investigation of the original behavior. section 1.2.1

