A Bug's "Done" Status Never Closes the Root Cause

Two defects recurred on seams that were already in the pattern bank. Both earlier fixes were applied at data level, and the RCA item was closed the moment the ticket went Done. What a real closure rule looks like.

Two defects came back on seams we had already documented.

Both were in the pattern bank. Both had been found before, analysed before, fixed before. And both re-escaped, on a programme that was running escape analysis every sprint and producing charts that showed defects being resolved.

Writing down the corrective-action loop is what finally explained it, and the explanation is embarrassingly simple.

What Actually Happened Both Times

The earlier fixes had been applied at data level. Correct the records, retest, the symptom is gone.

The cause was never verified as removed. And the root-cause item — the thing that was supposed to prevent recurrence — had been closed the moment the bug ticket went to Done.

A closed bug feels like a closed loop. The ticket is green. The retest passed. The sprint moves on and the burndown looks healthy.

But the symptom is gone and the cause is gone are two different claims, and our process had no step that ever asked the second one.

Why This Is Invisible From Inside

Every metric was working as designed. Defects raised, defects resolved, mean time to fix — all healthy, all improving.

Recurrence is the only metric that would have shown the problem, and recurrence is uniquely easy to lose. It depends on recognising that today's ticket and a ticket from three sprints ago are the same underlying fault, which requires someone to hold both in their head at once. Nothing in a defect workflow does that for you.

So a known seam re-escaped twice while the dashboard showed a programme getting steadily better at fixing things. Which it was. It was not getting better at removing causes, and those are different capabilities.

The Closure Rule

An RCA item closes when both of these are true:

  • A guarding test exists in the regression baseline. Not planned, not drafted, not "we should add." Present, and running in the cycle.
  • The following cycle shows no recurrence of the pattern. One clean cycle after the guard exists.

Until then it stays open, regardless of what the bug ticket says.

The consequence is that RCA items outlive the defects that spawned them, usually by weeks. That is not a process failure. It is the entire point. An RCA item that closes on the same day as its bug has not analysed anything — it has documented a fix you had already made.

What Makes the Guard Real

Two failure modes to watch for, because both produce an RCA item that closes on paper and protects nothing.

A guard on the instance, not the pattern. If the defect was a discount missing from an invoice, a test asserting that discount on that invoice guards one row of data. The pattern was "a value-bearing item fails to reach a downstream artefact." Guard the pattern, or the next instance walks straight through.

A guard that lives outside the baseline. A test written into a sprint-specific suite that nobody runs again is a comment with extra steps. If it is not in the regression baseline, it does not exist as a guard.

Making It Cheap Enough to Actually Do

None of this needs a tool, and it survives being simple.

  • One field on the RCA item: the guarding test's ID. Empty means the item cannot close. That single constraint does most of the work, because it forces the guard to exist as an artefact rather than an intention.
  • A standing query for the state that predicts escapes. The cheapest one available to a test lead: stories in a forward status whose linked defects are still open. A story can move to a deployment-ready state while its own bugs sit in development — nothing in a typical workflow stops it — and when those bugs resurface downstream they get counted as escapes against testing, even though QA found them on time.
  • A short recurrence check when triaging. Before a new defect gets a priority, one question: have we seen this shape before? If yes, it is not a fresh low-priority ticket. It is evidence about a cause that was never removed, and it belongs to the earlier RCA item rather than to a new one.

That last one has a very concrete failure mode. A defect arrived with the exact same summary as one raised two releases earlier — same error, same integration, same message — and was triaged as Lowest. Recurrences are escape-analysis gold. Scoring one as noise throws away the most informative ticket of the sprint.

The Honest Version

Root cause analysis without a verification step is documentation of fixes you already made.

It reads well. It fills a section in the report. And it will let the same seam fail three times while every number on the dashboard says the process is working — which is a more comfortable failure than most, and therefore the one likeliest to survive.

When did an RCA item on your programme last stay open longer than the bug that created it?