How I debug
The first reasonable hypothesis is usually wrong
It is the rule that saves me the most time, and the problem is precisely that the hypothesis is reasonable: it explains the symptom well enough for me to stop looking. The bug that costs a lot is almost never the one that resisted investigation: it is the one that accepted a plausible explanation too early.
That is why my routine does not start with understanding. It starts with reproducing.
The routine
- Reproduce before theorizing. Without a reproduction, any fix is a guess that looks like a solution. And whoever fixes without reproducing does not find out they fixed something else
- Isolate down to the smallest thing that still fails. Half of the bugs explain themselves along the way, before I form any theory
- Trust the measurement, not the memory. If I think the dependency is there, I look. “I’m almost sure” is the start of most lost hours
- Distrust silent success. An exit code read through a pipe lies, a log with no error is not proof that it ran, and a process that ends too fast usually did nothing
- Read what the system actually executes, not what the code suggests it executes: the effective pipeline, the resolved configuration, the included template, what actually went up
The fourth and the fifth are the ones that have caught me the most over time, and both have the same root: there is a distance between what the code says and what the machine does, and it is larger than it seems.
Recording the friction
I keep a friction journal. When a problem costs more than one attempt and the symptom pointed to the wrong cause, it becomes a line with date, symptom, real cause and cost. Typos do not go in, nor does what the next person would find out on the first try, and that bar is what separates a useful journal from a list of everything that went wrong.
The value is not in remembering the bug. It is that the patterns show up: rereading the pile you can see that a whole class of problem has a common origin, and then the right fix is at the origin, not in the case.
Today that capture is automatic and feeds The cycle that feeds itself, which cross-references the pile and proposes the tool that solves the whole class.