The FAIM learning communityKnowledge for the journey ahead

Debug with Evidence Before Changing Code

Turn a vague bug report into a reproducible case, a focused hypothesis, and a verified correction.

Debug with Evidence Before Changing Code

A bug report often arrives as an interpretation: the login is broken, the page is slow, or the database lost something. Those statements may point toward a real problem, but they do not yet describe what happened. Effective debugging begins by separating the observation from the explanation and building a case another person can reproduce.

Capture the smallest useful report

Ask what action was attempted, what result was expected, and what appeared instead. Record the environment and the relevant sequence of steps. A screenshot may help explain a visual symptom, while a request identifier can help locate server events. Avoid copying passwords, session cookies, or private customer content into a ticket just because they appeared nearby.

Try to reproduce the issue with a safe test account and the smallest relevant data set. If the symptom only occurs after a particular sequence, preserve that sequence. Removing too much context can make the problem disappear without explaining it. Your goal is a compact reproduction, not an artificially simple story.

State a hypothesis that can be disproved

Replace a broad guess such as the cache is wrong with a testable prediction. For example: this response is reused after the account changes, so requesting the same resource with a different account should reproduce the incorrect content. A useful hypothesis tells you what observation would support it and what observation would make you look elsewhere.

Change one variable at a time. Compare a failing request with a successful one, inspect the difference, and follow the request across the system boundary where behavior first diverges. If a browser sends the correct identifier but the API retrieves another record, the investigation now has a narrower location and a more precise question.

Use logs as evidence, not as a substitute for reasoning

  • Record event names, timings, and identifiers that support the investigation.
  • Prefer a request or correlation identifier over repeated personal data.
  • Distinguish a timeout from a confirmed failure or confirmed success.
  • Check the error returned to the caller as well as the internal event.
  • Remove temporary diagnostics that are no longer needed.

A stack trace can show where an error surfaced without showing where the incorrect assumption began. Read the surrounding control flow and the relevant input validation. Likewise, a successful status code does not prove that the intended state was saved. Inspect the durable result when persistence is part of the behavior.

Verify the correction against the original case

Once you understand the cause, choose the smallest change that restores the intended rule. Re-run the reproduction, then check a nearby case that could be affected. A focused regression test should describe the behavior that failed, rather than merely repeat the implementation's internal steps.

Write a short explanation for the next maintainer: the triggering condition, the incorrect assumption, and the resulting behavior after the fix. Include any remaining uncertainty. This record helps prevent the same investigation from starting again under a different ticket title.

During your next debugging session, pause before editing and write one sentence beginning with: if this hypothesis is correct, I should observe. That sentence can turn a series of hopeful changes into an investigation with a clear direction.