Bug Report Template: Examples That Get Fixed Faster
A bug report template used by real QA teams, three filled examples (UI, API, crash), and the research on which fields actually get bugs fixed faster.
A bug report has one job: make the fix cheaper than the triage. Every sentence either moves a developer toward reproduction or sends them back to you with questions. The reports that bounce around a backlog for weeks are not badly written — they are incomplete in the same three ways every time: no exact environment, no exact data, no observable expected behavior. This guide gives you the template that survives review, three filled examples for the common report types, and the research-backed reasons each field earns its place.
What the research says about bug reports
The most-cited study on this exact question — Bettenburg, Just, Schröter, Weiss, Premraj, and Zimmermann, "What Makes a Good Bug Report?" (Foundations of Software Engineering, 2008) — surveyed 466 developers and reporters across the Apache, Eclipse, and Mozilla projects. When developers ranked which information actually helps them fix a bug, the top fields were consistent and specific:
| Field | Ranked value to developers | What it prevents |
|---|---|---|
| Steps to reproduce | #1 — the single most important field in the study | "Cannot reproduce" → ticket closed, bug survives |
| Stack traces | #2 — developers read them before the description | Re-deriving the failure path from symptoms |
| Error messages | #3 — exact text, not paraphrased | Grepping the codebase for the wrong string |
| Test cases / input data | High — a failing input is a failing test | Round trips to ask "what exactly did you enter?" |
| Environment details | High — version, OS, browser, build number | "Works on my machine" arguments |
| Severity / priority guesses | Low — developers re-triage anyway | Inflated urgency that trains triage to ignore it |
The study's practical conclusion matches what triage teams learn the hard way: a report with exact repro steps, the stack trace, and the verbatim error message is fixable in one pass. A report missing all three is a conversation starter, not a bug report. The template below is built directly from those findings.
The template
Copy this structure into Jira, GitHub issues, or your tracker of choice. Field order matters: summary first because triage reads only that line, environment and repro steps next because they gate everything else:
Title: <Component>: <what happens> <when/trigger>
e.g. "Checkout: total shows $0.00 after removing
the last item from cart"
Severity: Blocker | Critical | Major | Minor | Trivial
Priority: P0 | P1 | P2 | P3 (set in triage, not by reporter)
Environment:
- App/version: v2.14.3 (staging build 2026-09-05)
- OS/browser: Windows 11, Chrome 140
- Account/role: qa_user@example.com, standard user
- Feature flag: checkout-v3 = on
Preconditions:
- Cart contains exactly 1 item ($25.00)
- User is logged in
Steps to reproduce:
1. Open /cart
2. Click "Remove" on the only item
3. Observe the order total line
Actual result:
- Total displays "$0.00" ...and (this is the bug) ...what exactly?
Expected result:
- Total displays "$0.00" AND the "Proceed to checkout" button is
disabled; today it is enabled and the next screen errors.
Evidence:
- Screenshot: link
- HAR/video: link
- Request IDs: req_9f2c1a
Notes/links:
- Started after the 2026-09-04 deploy; TC-CART-011 also fails.
- Possibly related: JIRA-1234. Two fields get deleted by every team eventually, so be honest about them: Priority belongs to triage, not the reporter — include it only if your process expects a recommendation. And "Severity" is about impact, not effort: a typo on the invoice page that prints the wrong currency symbol is Minor severity even though the fix touches money code.
Severity and priority, quickly
Teams argue about these two words more than any other part of the template. The distinction that survives review: severity is the impact if the bug ships, priority is the order you fix it in — and priority is a business decision, not a QA one.
| Level | Severity (impact) | Example |
|---|---|---|
| Blocker | Workflow stops; data loss or security exposure | Editor paste loses the last paragraphs (Example 3) |
| Critical | Core feature wrong for all users; wrong data served | API returns refunded orders to integrations (Example 2) |
| Major | Feature broken for a common path; workaround exists | Avatar upload silently fails (Example 1) |
| Minor | Cosmetic or edge-path defect; no user harm | Wrong currency symbol on a rarely seen invoice line |
| Trivial | No functional impact | Misaligned label on a settings toggle |
Example 1: UI bug, written well
| Field | Value |
|---|---|
| Title | Settings: avatar upload accepts a 20 MB file, then the page hangs for ~30s and silently fails |
| Severity | Major |
| Environment | App: staging 2026-09-06 · Browser: Chrome 140, macOS 15 · Account: qa_user@example.com |
| Preconditions | Logged in; no avatar set. |
| Steps | 1. Open /settings/profile. 2. In "Avatar", click "Upload" and select avatar_20mb.png (attached). 3. Wait on the settings page. |
| Actual result | Upload button shows a spinner ~30s, then reverts. No error message. Console shows 413 Request Entity Too Large on POST /api/avatar. |
| Expected result | Either the file picker rejects files >5 MB up front with "Images must be under 5 MB", or the 413 surfaces as an inline error. Silent failure is the bug. |
| Evidence | screen-recording.mp4; console screenshot attached. |
| Notes | TC-PROFILE-007 (5 MB boundary) also fails — same root cause. |
What makes this one land: the reporter separated the symptom (hang, silent revert) from the mechanism (413 in console) from the product expectation (reject early or show the error). The developer can start at the network layer without re-deriving any of it.
Example 2: API bug
| Field | Value |
|---|---|
| Title | API: GET /v2/orders ignores the status filter and returns all orders |
| Severity | Critical (wrong data exposed to integrations) |
| Environment | api.staging.example.com, token for test-tenant-7 |
| Preconditions | Tenant has 3 orders: two "paid", one "refunded". |
| Steps | 1. GET /v2/orders?status=paid with the tenant token. |
| Actual result | HTTP 200. Body lists all 3 orders, including the refunded one. Response header X-Total-Count: 3. |
| Expected result | Only the 2 paid orders; X-Total-Count: 2. Per docs (link to API reference section), status is a strict filter; unknown statuses must 422, not be ignored. Verified that ?status=bogus also returns 200 with all orders. |
| Evidence | request.har; response JSON attached. |
The extra probe — ?status=bogus — turns a single bad
response into a diagnosis: the parameter is ignored entirely, not
mis-mapped. Probing once before filing saves the assignee a round trip.
To run this kind of check yourself before writing it up, the
API Tester fires the requests
and shows status/headers side by side, and the
JSON Formatter makes the
response diffable when you attach evidence.
Example 3: crash / data-loss bug
| Field | Value |
|---|---|
| Title | Editor: pasting 50k+ characters freezes the tab (Chrome) |
| Severity | Blocker for the docs-team workflow (no data loss observed) |
| Environment | app v2.14.3 staging; Chrome 140, Windows 11 |
| Preconditions | Any document open with edit rights. |
| Steps | 1. Paste a 52,000-char text (file attached: bigpaste.txt). 2. Attempt to type within 2 seconds. |
| Actual result | Tab freezes 8–12s, then recovers. Last 1–2 paragraphs of the paste are missing after reload (autosave raced the freeze). |
| Expected result | Paste completes within ~1s; nothing lost. (If a size cap is intended, surface it as a message instead of freezing.) |
| Evidence | bigpaste.txt; before/after screenshots; doc ID doc_771. |
| Notes | reproducible 4/4 on staging; not reproducible on the 5k paste, so the trigger is roughly >20k chars. |
Note the boundary hunting: "reproducible at 50k, not at 5k" converts a crash report into a starting point for the fix. Severity stays Blocker because data loss occurs, even though the freeze alone would only be Major.
Why this template works: the triage math
- Title as a filter. Triage scans titles. Component-prefixed, trigger-suffixed titles let an owner self-assign without opening the ticket.
- Environment as a gate. "Works on my machine" arguments end when the build number, browser, and flags are in the report. Flag-dependent bugs (the checkout-v3 example) are undiscoverable without this field.
- Exact steps as the reproducibility contract. A report that another person can run verbatim is reproducible by definition. Everything else is commentary.
- Actual vs expected as two lines. When the expected result is missing, developers guess product intent — usually by asking the reporter, a day later. State the intent inline, and cite the spec line if one exists.
- Evidence as leverage. A HAR file or request ID turns "cannot reproduce" into a server-log lookup. For network issues, capture the exchange: our guide to debugging DNS, SSL, and headers covers reading what the HAR shows.
Common anti-patterns
- "It doesn't work." No component, no action, no expectation. Bounces at triage.
- Multiple bugs in one report. Three bugs, one ticket = one fixed, two forgotten. Split them; link them if related.
- Screenshots without text. A screenshot of an error message cannot be grepped or translated. Paste the message text too.
- Opinions in the title. "Checkout is a disaster" is not a title. State the behavior; the opinion goes in discussion.
- Missing build/env. A fix verified against the wrong build looks like a regression next sprint.
When a reported bug turns out to be an input-validation gap, that is a test-case gap wearing a disguise — fold it back into the suite. Our guide on how to write test cases covers the follow-through: turn every escaped bug into at least one new case that would have caught it.
Tooling notes
If your team uses Bugzilla, the Mozilla project's own bug-writing guidelines predate and match this structure — severity/symptom separation included. Chromium's bug reporting guidelines add the same advice from the browser side: exact version numbers and minimal repro steps. The template above is deliberately compatible with both, so reports stay portable across trackers.
Related reading
- How to Write Test Cases (Examples + Template) — the artifact that catches the bug before the report exists.
- How to Generate Realistic Test Data for QA — exact test data is half of reproducibility.
- Website Status Checker — attach an objective "server was up" reading to reports that might be environment-side.