The bug report template that actually gets bugs fixed
A good bug report answers four questions without a follow-up call: what did you do, what did you expect, what happened instead, and where's the evidence. Every field in the template below exists to answer one of those. Copy it as is, or take the GitHub and Jira variants further down.
The template
## TitleOne sentence describing the symptom, not the suspected cause.## Environment- Browser and version:- OS and device:- Deployed release or commit:- Account / role (if relevant):## Steps to reproduce1. Start from a fresh session at <URL>2.3.## ExpectedWhat should have happened, in one sentence.## ActualWhat happened instead, in one sentence.## Evidence- Console errors (paste the full message and stack):- Failed network request (method, path, status):- Screenshot or recording:## Regression?Did this work before? If yes, roughly when did it break?
That's the whole thing. Seven sections, and most reports won't need all of them. Resist the urge to add more fields; every extra box lowers the odds anyone fills in the ones that matter.
How to write a bug report worth reading
Write the title as the symptom: "Order total doesn't update when quantity changes", not "Cart bug" and not "Race condition in CartSummary". The first is searchable and specific. The last is a guess dressed as a diagnosis, and it sends whoever picks up the ticket down your theory instead of the evidence.
Number the repro steps from a fresh session. Half of all unreproducible bugs are unreproducible because the reporter started from state the reader doesn't have: logged in, cart pre-filled, feature flag on. Step 1 should be a URL a stranger can open.
Keep expected and actual to one sentence each. If you need a paragraph for either, the report is probably describing two bugs. File two.
The evidence section is the one that decides how fast the fix happens. A pasted console error with its stack turns an afternoon of guessing into a file and line. The failed request's method, path and status narrows it further. I'd trade every other field for these two.
And the regression question is cheap for the reporter and gold for the fixer. "Worked last Tuesday" plus a release number turns debugging into a diff between two versions.
A filled-in example
## TitleOrder total doesn't update when quantity changes on the cart page## Environment- Chrome 139, macOS- Release v1.4.2- Logged in, regular customer account## Steps to reproduce1. Start at https://shop.example.com/cart with one item in the cart2. Change the quantity field from 1 to 33. Look at the order total## ExpectedTotal updates to $36.00 (3 × $12.00).## ActualTotal stays at $12.00 until a full page refresh.## Evidence- Console: TypeError: Cannot read properties of undefined (reading 'total') at recalcCart (cart-DZk1.js:2:18410)- Network: POST /api/cart/recalc returned 500- Screenshot attached## Regression?Worked on v1.4.1 last week.
Notice what the example doesn't contain: no severity matrix, no priority score, no speculation about the cause. Priority fields get argued about in comments; a 500 with a stack trace doesn't.
GitHub and Jira variants
For GitHub, save this as .github/ISSUE_TEMPLATE/bug_report.yml and the form enforces the structure for you:
name: Bug reportdescription: Something brokelabels: [bug]body: - type: input id: title-symptom attributes: label: Symptom placeholder: Order total doesn't update when quantity changes validations: required: true - type: textarea id: environment attributes: label: Environment placeholder: Browser, OS, release/commit, account state validations: required: true - type: textarea id: steps attributes: label: Steps to reproduce placeholder: "1. Start from a fresh session at <URL>" validations: required: true - type: textarea id: expected-actual attributes: label: Expected vs actual validations: required: true - type: textarea id: evidence attributes: label: Evidence placeholder: Console errors, failed requests, screenshot
In Jira, map the same sections onto the description template of your Bug issue type rather than custom fields. Custom fields feel rigorous but they're where evidence goes to die; a description template keeps the console output next to the steps that produced it.
Where templates run out
A template can only ask. The fields that decide fix speed, meaning the console error, the failed request and the release, are exactly the ones reporters can't reliably transcribe, because that context lives on the page at the moment of the bug and is gone by the time they're filling in boxes. Templates raise the floor; they can't raise the ceiling.
That ceiling is why we built Rebase: its widget captures the recent actions, console errors and failed requests when the customer opens it, so nobody has to copy them out. The strongest reports go one step further and contain a failing test instead of prose. Use the template for everything else. It's how bugs got fixed for decades before capture tools, and it still works.