How to write a bug report that gets fixed
How to write a bug report an engineer can act on without a round trip. The usual failure is not a missing field — it is describing your conclusion instead of what happened.
Someone files "checkout is broken". An engineer opens it, cannot reproduce anything, asks two questions, waits a day, gets one answer back, and guesses. That round trip usually costs more than the fix does.
The standard advice for this is a template. Templates help a little, but the reports that stall are rarely missing a field — plenty of them are long. They fail because the reporter wrote down the conclusion they reached instead of the thing that happened. "Checkout is broken" is a diagnosis. What the reporter saw was a spinner that never stopped after clicking Pay, on one order, twice. That is a bug report; the first is a mood.
So how to write a bug report is not a question about which fields to fill in. Separate what you observed from what you concluded, and put the observations first. Simon Tatham's essay has the rule in a line: "always state the symptoms. The diagnosis is an optional extra" (chiark.greenend.org.uk). This is for whoever is filing, engineer or not. Done means the person who picks it up can start without asking you anything.
How to write a bug report in eight steps
-
Title the symptom, not the guess. Mozilla's bug writing guidelines say a summary "should explain the problem, not your suggested solution" (bugzilla.mozilla.org). "Cache invalidation on invoices" commits everyone to your theory before anyone has looked. "Download invoice returns a 500" survives being wrong.
-
Write what you did, as steps someone else can follow. Numbered, from a state they can get into: signed in as whom, which record, which screen. Mozilla calls steps to reproduce "the most important part of any bug report", because a bug a developer can reproduce is very likely to get fixed.
-
Write what happened, in the system's own words. Not "it errored" — the error text, the status code, the reference number. Numbers in error messages exist to be looked up, and a paraphrase throws away the only unique thing in the report. Screenshot the error rather than summarising it; the image holds the details you did not know mattered. Paste the text too, so it stays searchable.
-
Write what you expected. This feels redundant and changes the outcome more often than any other line. Half the time it reveals you disagree about intent rather than about code — a product question, not a bug. The rest of the time it says which of several correct behaviours you were counting on.
-
One bug per report. "Open a new bug report for each issue", as Mozilla puts it, so each can be closed on its own. A report carrying three problems gets partly fixed and then closed, and the other two are gone.
-
Say how often, honestly. "Every time" and "once" are different engineering problems. If it happened once and you cannot make it happen again, say exactly that and file it anyway, with the time and what you were doing thirty seconds earlier. Those reports get thrown away, and they are worth keeping: the second one arrives in three weeks and the pair have a pattern neither had alone. Mozilla takes the other view — without reproduction "there's probably no use in reporting it, unless you provide unique information about its occurrence" — right for a tracker fielding thousands of reports from strangers, wrong for six people who know each other.
-
Include the environment facts that change the answer, skip the rest. Browser and version, OS, which account, whether anyone else can reproduce it. A paragraph of the rest is a field existing rather than a field being load-bearing — the test we applied to every field on a board in what a five-person team actually needs from issue tracking: who reads this, and what changes depending on what it says.
-
State severity as impact on a person, not as a feeling. "Urgent" is not information. Mozilla's severity field describes "the scope of a bug's effect" (firefox-source-docs.mozilla.org): S1 is data loss with no workaround, S2 is major functionality "severely impaired", S3 has a workaround, S4 is cosmetic with "low or no impact to users" (wiki.mozilla.org). Write the sentence that generates the label — who is blocked, from doing what, and is there a way round it.
Then file it where the reply can find you. A report in a chat thread gets one answer and scrolls away; it needs an address. In Kevta the follow-up questions live in the comments on the issue, with every field change in the activity feed underneath, so "reproduced, it was the timezone" stays attached to the report. Want a reproduction field? Add a custom text property — no scheme to design first. And whoever filed can press Watch to hear when it closes without being the assignee (the tasks docs have the mechanics). One limitation, since it bears on step 3: Kevta has no file attachments, so screenshots have to be links.
A bad bug report
Not a straw man — a competent report from someone busy, which is what most of them look like:
Title: Invoices are broken again
The invoice PDF isn't generating for customers on the new plan.
Pretty sure it's the same caching thing from last week. Can someone
look before the weekend? Marking this urgent.
Three sentences, three conclusions, no observations. "Customers on the new plan" is a hypothesis about scope, probably from a sample of one. "The same caching thing" sends the first hour of debugging somewhere the reporter cannot justify. "Urgent" is a feeling. And nothing says which invoice or what appeared on screen, so the engineer's first action is to write a message and wait.
A good bug report example, same bug
Title: Download invoice returns a 500 for INV-2841
What I did
1. Signed in as support, impersonating sam@example.com (workspace 812)
2. Billing → Invoices
3. Clicked Download on INV-2841 (dated 3 August)
What happened
A new tab opened and rendered blank. Body text read "Something went
wrong. Reference 9f21c4." Response was 500. Screenshot in a comment.
What I expected
The PDF to download, which is what Download on INV-2840 does from
the same list.
How often
Three times in a row just now on INV-2841. INV-2840 and INV-2839
download fine for the same account.
Environment
Chrome 128 on macOS. Reproduced on Firefox by someone else.
Impact
This customer's finance team is asking for the document and we
cannot give it to them. One customer so far, no workaround.
Same amount of typing. Every line is something the reporter saw, and the reference number means someone can find the failure in the logs before touching the code.
What the receiving side owes the reporter
The half of this that guides skip. A report that vanishes teaches the reporter to stop filing, and that is how a team loses its early-warning system.
- Acknowledge it quickly — not a fix, just evidence a person read it. Four days of silence teaches the reporter that filing wastes their time.
- Say what it is. Reproduced; need one more thing; real but not this week; working as intended, and here is why. All four are fine. Silence is not.
- Ask for what is missing as a specific question. "Get me the reference number off the error page" is answerable in a minute. "Can you give more detail" is not.
- Close the loop when it ships, without the reporter having to check.
- Fix the reports, not the reporters. If support keeps filing thin ones, reply once with the six lines you wish had been there.
Skip it and reports stop arriving, everyone concludes there are fewer bugs, and the signal moves to a channel nobody searches — the same mechanism that makes nobody update the board.
The trade-off: a heavy template is not free
A long bug report template with required fields does raise the quality of the reports you get. It also lowers the number of them, and on a small team the second effect is usually the larger one.
The person best placed to notice a bug is often the least willing to fill in a form: the support contact between two conversations, the designer who saw something odd on the way to something else. Give them fourteen fields and a mandatory reproduction section and some will mention it in chat instead. A bug mentioned in chat is a bug you do not have.
So for most small teams, a low-friction report you can ask questions on beats a form nobody completes. Three headings — did, happened, expected — plus a line on frequency and one on impact. Heavy templates earn their keep when the reporter and the fixer will never speak, which is probably not you. With no dedicated tester the same logic runs through the rest of the process, which we wrote up in bug tracking for small teams without QA.
Disclosure
We build an issue tracker, so read that paragraph with the suspicion it deserves. Kevta is in beta: stable issue keys, comments and activity on the issue, custom fields with nothing to configure, watching a task you filed but do not own. No attachments, no reporting layer, no QA workflow. The waitlist is on the front page.
Whatever you use, the test survives. Read your next bug report back and mark every sentence as either something you saw or something you concluded. If the conclusions outnumber the observations, that is the round trip, and you can delete it before you press send.
- bug-tracking
- process
- small-teams