What a tester notices is the manifestation of a problem: an error message, a wrong number, a missing button. But what's visible on the screen is almost never the defect itself — only its symptom. Between "what I see" and "what is actually broken" lies a chain of causes, and the lower you descend along it, the more useful your bug report becomes — and the faster the defect gets fixed. The systematic descent along this chain is called root cause analysis.
Symptom → causes → root cause
The worst case: the problem isn't noticed at all. Slightly better: the report describes only the outward manifestation ("the report sometimes won't open"). Acceptable: the surface-level causes are described. The ideal is to reach the two lowest levels of the chain:
- The root cause — the specific flaw that spawns the whole tree of consequences.
- The conditions that enabled it — why the flaw appeared in the first place (this is more often a question about the process than about the code).
The whole idea fits into three questions: what happened, why it happened, and how to reduce the likelihood of recurrence. Eliminating the root cause is worth more than patching a symptom: an unfound root cause will keep spawning new defects — in other places and other shapes.
An example: descending the chain
A real-world example. A console utility processes folders; a command with the absolute path /var/www returns the error "SOURCE_DIR name [var/www] is not a valid directory" — although the folder exists and is accessible.
- Manifestation. In the error message the folder name differs from what was entered: the leading
/is gone. A few control runs confirm: the leading slash disappears in all parameters. - Cause N. We try relative paths — they work. We try Windows — it works. So the issue is in how entered names are processed. Hypothesis: leading and trailing slashes are being stripped.
- Cause N-1. Runs with paths like
\\\\c:\\\\confirm: the application removes all slashes at the beginning and end of a name, in any quantity. - Root cause. Hypothesis: somewhere in the code there's a primary path filter, and it works incorrectly. Looking into the parameter-parsing code (or asking the developer), we find the method that "canonicalizes" the name and trims edge separators. For Linux this is fatal: every absolute path starts with a slash.
Now compare two reports. "The application doesn't detect accessible folders" describes the symptom: it's factually inaccurate, and the whole investigation lands on the programmer. "Stripping edge / and \ from launch parameters breaks absolute paths on Linux" describes the root cause: the developer only has to fix a specific method.
The search algorithm
The universal sequence:
- Define the manifestation. What exactly happens, and why is it bad?
- Gather information. Does the same happen in other situations? Always in the same way? What does the problem's appearance or disappearance depend on? This is the same move as varying conditions in exploratory testing.
- Form a hypothesis about the cause. What could be causing it? Which actions or conditions trigger the manifestation?
- Test the hypothesis with additional experiments. Not confirmed — form another one.
- Make sure you've found the root cause, not just another link in the chain. If it's an intermediate link — repeat the algorithm for it. If it's the root cause — state what to fix and where.
Reading the code isn't mandatory (though useful if you can): well-designed external experiments plus asking the developer "where in the code could this be handled?" often suffice.
Where this applies
Every "flaky" bug is a root cause analysis that wasn't carried through: "sometimes" reproducibility means precisely that the pattern hasn't been found. Every report bounced with "cannot reproduce" is most often a symptom description instead of a cause. And conversely: a tester who brings not "something broke" but "it breaks here, this is why, and these are the conditions" saves the team hours and quickly earns a reputation as a strong specialist. The algorithm itself — define, gather, hypothesize, verify — is universal: it works in debugging, in production incidents, and far beyond IT.
Where beginners stumble:
- They file a report on the first manifestation without a single extra check. Five minutes of experiments often turn "sometimes doesn't work" into a clear pattern.
- They stop at the first cause and take it for the root cause. Ask yourself: "and why does that happen?" — as long as the question has an answer, you haven't reached the bottom of the chain.
- They bend facts to fit the hypothesis. A hypothesis you haven't tried to refute is not a tested hypothesis. Look for the experiment that could break it.
What to learn next. How to shape what you found into a report that gets fixed — in the bug report quality article; where the "error → defect → failure" chain comes from — in the what-is-a-bug article; the condition-varying technique — in the exploratory testing article.