Skip to content
Mastering Claude

Home / When things go wrong

When things go wrong10 minApplication

Read the function called next, prove the culprit

A fix whose unit test goes green can be undone, within the same execution turn, by the function called right after it, and the already fixed function only becomes a proven culprit once a test has isolated its effect from that of the functions that follow.

A fix that corrects exactly the faulty function, with a unit test that goes green, can change nothing the user actually sees. The reason comes down to one thing: the function you just fixed is almost never the last one to touch the value. The corrected result still passes, within the same execution turn, through one or more functions called right after it, and one of them can undo the fix without any test flagging it.

The fix that does not survive the next call

Take a case built to stand on its own, with no dependency on any project file. The function formatPrice used to round a price in cents incorrectly, the fix now makes it round to two decimal places. Its own test passes. The price displayed on screen is still wrong, though, because a function applied right after it, applyDiscount, turns that text back into a number and then rounds it down a second time.

function formatPrice(cents) {
  return (cents / 100).toFixed(2); // fixed: exact two decimal places
}

function applyDiscount(priceText) {
  const price = parseFloat(priceText);
  return Math.floor(price * 0.9); // rounds again, downward
}

console.log(formatPrice(1299));                 // 12.99, the fix works on its own
console.log(applyDiscount(formatPrice(1299)));  // 11, the fix is undone

The first call proves that formatPrice is correct. The second call, the one that actually reaches the screen, proves the opposite. A fix is proven on that second figure, never on the first.

The plausible culprit is not the proven culprit

Faced with a display that is still wrong after a fix, the function already changed becomes the prime suspect again. That is a plausible culprit, not a proven one. To settle it, read the first and last instructions of every function called right after the one that has just been fixed, not just that function on its own. In the example, the last instruction of applyDiscount, Math.floor, is the line that wipes out the cents formatPrice had just restored.

The final proof is not read in the code, it is read in an output. Write a test that isolates exactly the input and the output visible on screen, in this case the value applyDiscount returns, and read what that test actually returns before naming a culprit. It is the same principle as checking the actual state before acting on a request: a fix is established on the output produced, never on a reading of the code supposed to produce it.

When the culprit stays undetermined

Two functions called in the same turn can each alter the same value in a way that, taken in isolation, produces a plausible result. A test that does not separate their effects settles nothing. In that case, the correct answer is not to pick a function at random to close the matter: it is to write two separate tests, one per suspect function, each isolating it from the other, and then to say that the culprit's identity stays undetermined until both tests have been run and read.

Figure 1

From the fix applied to a settled verdict

01
Fix applied
The function identified as faulty is fixed, and its own unit test goes green.
02
Next function called
The corrected result is passed on, within the same execution turn, to a function called right after it.
03
Plausible culprit named
A display that is still wrong names the already fixed function as the prime suspect again, with no new evidence.
04
Instructions read to the end
The first and last lines of every function called next are re-read, not just the one already fixed.
05
Verdict settled by a targeted test
A test that isolates the exact input and output confirms or overturns the chosen culprit.
The sequence shows why a fix whose own test goes green can still stay invisible on screen, and what is still missing to name a proven rather than a plausible culprit.
Calibrate it yourself

A developer fixes the function that rounds a displayed price, its unit test goes green, then he restarts the application and still sees a badly rounded price on screen.

Write, in one sentence, what this situation establishes, and in one sentence what it does not establish.

What to remember
  • A fix whose unit test goes green guarantees nothing about the screen if a function called right after it still touches the same value.
  • Reading only the function you just fixed leaves invisible everything that happens in the functions that follow within the same execution turn.
  • A plausible culprit remains a hypothesis until a test has isolated its exact input and output.
  • A fix is proven by the output a test returns, not by re-reading the code supposed to produce it.
  • When two suspect functions each alter the same value in a plausible way, the honest answer is to say the culprit stays undetermined until two separate tests have told them apart.
Do this now

Take a fix you applied recently without revalidating it with an isolated test, write a disposable function of a few lines that reproduces the exact chain between the fixed function and the one that calls it next, then run that test and read its output before continuing to trust the fix.