top of page

Writing Bug Reports That Actually Get Fixed

  • Shawn West
  • Jun 24, 2025
  • 9 min read

Updated: Aug 10

It's 9:15 on a Tuesday. A ticket lands in the queue: "The app is broken." No steps, no version, no screenshot, no account. Before anyone can fix anything, someone has to reconstruct what "broken" means — what the reporter did, on what build, what they expected instead. That reconstruction is real work, and the ticket just silently moved it from the reporter's desk to a developer's. Multiply one vague ticket by twenty a week and a serious slice of engineering time goes to interrogation instead of repair.

A bug report is a work order. When it's complete, a developer can walk up and start fixing. When it's incomplete, the missing work doesn't disappear — it reappears as guesswork on someone else's calendar. That framing is the foundation, and if you take nothing else from this piece, make your reports reproducible first: a stranger should be able to recreate the failure from your words alone. The companion piece Bug Report Template: What Makes One Useful walks the fields that get you there, so this article won't re-teach them.

But reproducibility is where the real problem starts, not where it ends. A perfectly reproducible bug can still rot at the bottom of a backlog for a quarter. Getting a report written is a documentation problem. Getting it fixed is a competition — your work order against forty others for the same finite pool of developer hours. This piece is about winning that competition.

Reproducible gets you into the queue. It doesn't move you up it.

Picture the backlog on the morning someone triages it. There are thirty-one open defects. Every one of them is, let's say, reproducible — the team writes decent reports. The triager has maybe an hour and enough team capacity to promote three or four of them into the current sprint. The other twenty-seven wait.

So the question that decides your bug's fate isn't "can this be reproduced?" Everyone in the pile cleared that bar. The question is "of the bugs I could fix next, why this one?" If your report only answers "here's how to reproduce it," you've made yourself eligible and then gone silent at the exact moment the decision is being made. The reports that get pulled forward are the ones that answer the triager's real question — who is hurt, how badly, how often — without the triager having to go find out.

Takeaway: After you've written a report you can reproduce, re-read it and ask, "Does this tell the triager why it should jump the queue?" If the only argument is "it's a real bug," you've written a record, not a work order that competes.

Severity is not priority — and confusing them is why good bugs stall

The single most useful distinction in triage is one that most reports blur into a single word: severity and priority are different things, set by different people, for different reasons.

  • Severity describes the failure itself: how badly the software misbehaves when the bug fires. Data loss is high severity. A crash is high severity. A label misaligned by two pixels is low severity. Severity is a property of the defect and is largely objective — a developer and a tester will usually agree on it.

  • Priority describes the response: how soon the team should spend hours fixing it, relative to everything else competing for those hours. Priority is a business decision. It weighs severity and who's affected, how often, whether there's a workaround, and what it costs the organization to leave it unfixed.

They come apart constantly, and the interesting bugs live where they diverge:


High severity (bad failure)

Low severity (minor failure)

High priority (fix soon)

Checkout crashes on card submit — every paying customer blocked, no workaround. Fix now.

Typo in the company name on the public pricing page — trivial failure, but it's on the page the CEO is demoing to investors tomorrow. Fix today.

Low priority (fix later)

Data corruption in a report export used by one internal analyst, once a quarter, with a known manual workaround. Schedule it.

Tooltip renders one pixel low on a settings screen few users open. Backlog.

Look at the top-right cell. A cosmetic bug — objectively low severity — outranks a data-corruption bug because of who sees it and when. That is not triage being irrational. That is priority doing its actual job: converting the failure into business consequence. A report that only shouts "this is SEVERE" hands the triager half the inputs and asks them to guess the rest.

Takeaway: In your next report, state severity and priority as two separate lines, and for priority, give the reason — "Priority: high — blocks every checkout, no workaround." If you can't write the reason, you've found the sentence your report is missing.

What a triager actually needs to decide this is next

Here's the discovery move, and it's the same move ShiftQuality applies everywhere: before you argue for the fix, figure out what the decider actually needs to make the call. A triager staring at thirty-one bugs is running a rough cost function in their head. The three inputs that feed it:

  1. Impact — what does the bug cost per occurrence? Lost revenue, blocked work, a support ticket, a moment of confusion? "Customer can't complete purchase" and "customer sees a slightly wrong date format" are different orders of magnitude, and the triager can't infer yours from a stack trace.

  2. Frequency — how often does it fire? A crash that hits every user on every login is a different animal from a crash that needs a leap-year date and a specific timezone. Impact times frequency is the number that actually moves triage.

  3. Severity — how bad is the failure when it does fire? This is the input reporters usually do supply, and it's the one that means the least on its own.

Most reports deliver input three and go quiet on one and two — the two the reporter is uniquely positioned to know, because they're the one who saw it happen in context. The triager can read severity off the symptom. They cannot read "this hit fourteen enterprise accounts during month-end close" off a screenshot. Only you can hand them that.

Takeaway: Before you submit, write one sentence in the form "This costs [impact] and happens [frequency]." If you can't fill both blanks, go find out — that sentence is the persuasion, and it's the part no one but the reporter can supply.

Two reports, one bug: the triage decision

(Developed example — composite scenario.)

Two engineers, working different areas, independently hit the same defect: on the checkout page, applying a discount code and then changing the cart quantity leaves the displayed total stale — it shows the pre-change price until the page is reloaded. Same bug, same root cause, filed the same afternoon. Both reports are fully reproducible; a stranger could recreate the failure from either one. Here is what each put in front of the triager.

Report A — "Cart total doesn't update after quantity change with discount applied."

Steps to reproduce, expected vs. actual, browser and build number, a screenshot of the stale total. Severity: Medium. Priority: (left blank.)

Report B — "Discounted checkout shows wrong total — customers can be charged a price they didn't see."

The same steps, expected vs. actual, build number, screenshot. Then: "Severity: Medium (display only; the charged amount is correct at the payment step). Priority: High. Impact: customers see a total that doesn't match what they're charged — this generates 'I was overcharged' support tickets and chargeback risk even though billing is technically correct. Frequency: any order that edits quantity after a code — we ran ~2,300 discounted orders last week, and discount campaigns are live through the holiday. Workaround: none the customer would think to try (reload)."

At triage, Report A reads as a medium-severity display bug with no priority set, so the triager defaults it to the pile — it looks like polish, and polish waits. Report B describes the identical defect but has done the triager's analysis for them: it separates severity (genuinely medium — nobody is mischarged) from priority (high — because of trust damage, support cost, and a live campaign making it frequent). The triager doesn't have to investigate blast radius; Report B handed it over. Report B gets pulled into the day's work. Report A waits for someone to rediscover, weeks later, that it was the same issue all along.

The lesson isn't "write more." Report B is barely three sentences longer. The lesson is what those sentences carry: not more detail about the failure, but the impact-and-frequency argument that lets someone else prioritize without redoing your investigation.

Takeaway: Steal Report B's structure — severity and priority stated separately and each justified, then one line each for impact, frequency, and workaround. That's the shape of a work order that gets picked up.

The impact sentence that moves triage

The center of gravity in Report B is one sentence: "customers see a total that doesn't match what they're charged." It translates a technical symptom into a business consequence, and that translation is the single highest-leverage thing you can add to a report.

Compare the two moves:

  • Symptom only: "The total doesn't refresh after a quantity change." True, and inert. It leaves the reader to work out whether that matters.

  • Symptom plus consequence: "The total doesn't refresh, so customers see a price that doesn't match their charge — that's a trust problem and a support-ticket generator during a live discount campaign." Now the reader knows the cost of not fixing it, which is the only thing priority actually weighs.

You don't need to inflate anything to do this honestly. If the real consequence is small — "an internal admin sees a stale count until they refresh a page they rarely open" — write that. A truthful small-impact sentence protects your credibility for the day you file a genuinely urgent one. Reporters who mark everything "critical" get the CSS-selector equivalent of ignored: triagers learn to discount them. This connects directly to how teams draw their fix-or-ship lines in Quality Gates That Actually Gate — a gate can only act on impact someone actually wrote down.

Takeaway: End every report with an explicit "If we don't fix this: ___" sentence. If the honest answer is "not much," say so — that honesty is what makes your "this one's on fire" land the next time.

A method you can run on your next report

Reproducibility first, then earn the fix. Once your report clears the reproducible bar (the template piece covers that), add four lines before you submit:

  1. Severity — with the failure named. "High — data loss," "Medium — display only, charge is correct," "Low — cosmetic." One clause of justification, so the reader trusts your rating.

  2. Priority — with the business reason, not the severity restated. "High — live campaign, no workaround, generates support tickets." This is the line reporters skip and triagers most need.

  3. Impact × frequency in one sentence. "Costs [X] and happens [how often / how many]." The number no one but you can supply.

  4. Workaround — or its absence. "Reload fixes it, but customers won't know to." Presence of a workaround is often what drops a high-severity bug to low priority; its absence is often what raises a low-severity one.

If a field genuinely doesn't apply, write "n/a" rather than leaving it blank — a blank reads as "the reporter didn't think about it," and thinking about it is the whole job. This is the same discipline that separates the checks that block a release from the ones that don't in Definition of Done vs Acceptance Criteria: naming the standard is what makes it enforceable.

Takeaway: Add the four lines — severity, priority, impact×frequency, workaround — to your team's report template as required fields. A required "priority reason" field does more for throughput than any amount of exhortation to "write better bugs."

Where this can steer you wrong

Framing impact is persuasion, and persuasion can be abused. Three honest limits:

  • You are advocating, not deciding. You supply impact and frequency; the triager still owns the call, because they can see the other thirty bugs and you can't. If everything you file is "high priority," you've stopped advocating and started crying wolf — and you'll be tuned out.

  • Don't smuggle severity into priority to jump the line. A cosmetic bug is low severity even when you argue it's high priority. Keep them honestly separate; the CEO-demo typo is low severity, high priority, and saying so is more credible than relabeling it "critical."

  • Your impact estimate is an estimate. "~2,300 orders last week" is far stronger than "this happens a lot," but if you're guessing frequency, say you're guessing. A triager who catches you inflating one number discounts all your numbers. When you truly don't know blast radius, the honest move is to say what you'd need to measure it — that's a legitimate finding for the person who can measure it, and it's the kind of scoping gap User Acceptance Testing (UAT): How to Run It Well is built to surface before release.

Takeaway: Audit your own last ten reports. If more than a couple are marked top priority, recalibrate — your credibility is the currency that makes the next urgent report move, and it spends down fast.

The report that gets fixed

A bug report that gets fixed does two jobs, and most reports do only the first. It lets a developer reproduce the failure — table stakes, covered by any decent template. And it lets a triager prioritize the failure without redoing your investigation — by separating severity from priority, and by handing over the impact-and-frequency argument that only the person who saw the bug in context can supply. The vague ticket reassigns your investigation to a developer. The complete work order does the opposite: it hands the next person everything they need to say yes. Write the second kind, and your bugs stop waiting for someone to rediscover why they mattered.

Sources

  • The severity-versus-priority distinction and the impact × frequency prioritization heuristic are standard software-testing practice, reflected in bodies of knowledge such as the ISTQB glossary and foundation syllabus.

  • The two-reports triage scenario, the checkout-discount defect, and all figures in it (order counts, ticket counts) are a composite illustration built to demonstrate the framing decision — not a record of a specific incident or company.

Keep learning. This article is part of the Software Testing Foundations path in the ShiftQuality Learning Center.

bottom of page