Good Bug Reports — Repro Steps Devs Actually Read
“It doesn’t work” is not a bug report. It is a distress signal. Engineers triage dozens of tickets a week; the ones that get fixed fast share a shape: enough context to reproduce, a clear wrong outcome, and zero mystery novels. Good reporting is a skill, not a personality trait.
The minimum viable report
- Summary — one line: what broke, where (e.g. “Checkout: Pay button stays disabled after valid card”).
- Environment — OS, app/browser version, build number, account type (free/paid), locale if relevant.
- Steps — numbered, starting from a known state (“Log in as …”, “Open …”).
- Expected — what should happen.
- Actual — what happened, including exact error text.
- Evidence — screenshot, short clip, or log snippet.
If any of 2–5 are missing, the ticket will bounce or sit idle while someone asks for them in comments.
Repro steps that survive contact with reality
Bad:
Go to settings and try changing stuff. Broken on my laptop.
Better:
- Log in as
[email protected](role: Editor).- Open Settings → Notifications.
- Toggle Email digests off, click Save.
- Refresh the page.
Expected: Toggle remains off.
Actual: Toggle returns to on; toast shows “Saved.”
Include data dependencies: empty project vs project with 10k rows often diverges. Mention feature flags if you know them.
Artifacts: useful vs noisy
| Artifact | Use when | Skip when |
|---|---|---|
| Screenshot | UI text, layout, wrong state | The bug is timing/audio only |
| 15–30s clip | Animation, race, gesture | Five minutes of wandering |
| Console/network HAR | API 4xx/5xx, CORS, failed fetch | Pure visual copy typo |
| Device logs | Crashes, native apps | Web CSS spacing issues |
Do not assume the developer knows your GPU, browser extensions, or corporate VPN. State them if the bug smells environmental.
Templates beat memory
Teams that paste a skeleton into every ticket get higher-quality reports from non-engineers. A short form with fields for environment and steps outperforms a blank text box. Generate a filled skeleton with bug-report when you want consistent sections without reinventing the outline each time — then delete empty fields so the ticket stays skim-friendly.
Severity vs volume
Label severity honestly:
- Blocker — cannot complete a primary flow; no workaround
- Major — wrong data or broken secondary flow; workaround exists
- Minor — cosmetic or rare edge
Mislabeling everything as blocker trains the team to ignore severity. Frequency (“happens every time” vs “saw once”) matters as much as impact.
What reporters should not do
- Paste entire console histories with unrelated warnings
- Argue about root cause in the first message (“definitely a Redis issue”)
- Duplicate open tickets without linking
- Edit reproduction steps silently after investigation started — add a comment instead
After you file
Stay reachable for one clarifying question. If you find a narrower repro, update the ticket. If it stops reproducing on a new build, say so — closing the loop is part of a good report.
For regressions, link the last known good build or release tag. “Works on 2.3.1, breaks on 2.4.0” saves hours of git bisect theater when the steps are otherwise identical.
Developers read reports that respect their time. Give them a path to fail the product the same way you did, once, on purpose. That is the whole game.