Bug Report Template: What to Include, With Examples
A bug report needs six things: a title that names the problem, the environment, numbered steps, expected and actual results, evidence, and severity. A template to copy, a bad report rewritten, a version an AI assistant can act on, and a shorter form for people outside the team.
7 min read
A useful bug report has six parts: a title that names the problem, the environment it happened in, numbered steps to reproduce it, what you expected against what actually happened, evidence such as a screenshot or error message, and how bad it is. With those, whoever picks it up, a colleague or an AI assistant, can see the bug for themselves before changing anything. Without them, the first hour of the fix is spent asking questions. Below is each field, a template to copy, a bad report and its rewrite, and shorter versions for agents and for people outside the team.
This page is about writing one report well. Running the list those reports land in is covered in tracking bugs and feature requests in one board and an issue tracker for AI agents, and the bug tracker template sets up a board for them.
The fields that matter
- Title. The problem, specifically, in a line. Mozilla’s bug-writing guidelines (opens in a new tab) contrast “Cancelling a File Copy dialog crashes File Manager” with “Software crashes”, and advise keeping it short and about the problem, not the fix.
- Environment. Where it happened: the app version or build, the device, the operating system, the browser and its version, the account or role, and whether it was live or a test copy. Many “cannot reproduce” replies come down to an environment nobody wrote down.
- Steps to reproduce. Numbered, starting from somewhere the reader can get to, with the exact values used. Say how often it happens: every time, sometimes, or once. These are the part most worth getting right, because a bug someone can reproduce is one they can fix.
- Expected and actual. Two short lines of fact. “Expected: the total drops by 10%. Actual: the total shows 0.00.” Not “it doesn’t work”.
- Evidence. A screenshot or recording, the exact error text, a log line, the time it happened. Paste error text as text so it can be searched.
- Severity. How bad the effect is, in plain words: data lost, a main task blocked, a workaround exists, or cosmetic. Say whether there is a workaround.
Two habits help as much as any field. One bug per report, because a report with three problems gets closed when the first is fixed. And keep guesses about the cause apart from what you saw, labelled as guesses, so nobody chases your theory instead of the symptom.
Severity is not priority
Severity describes the effect of the bug. Priority is the team’s decision about when to fix it. They usually agree, but not always: a typo on the home page is trivial in effect and may still be fixed today. Mozilla’s severity definitions (opens in a new tab) are a clear public example of a four-level scale: S1 catastrophic, such as data loss with no workaround; S2 serious, major functionality impaired with no satisfactory workaround; S3 normal, non-critical or with a workaround; S4 small or cosmetic. Let reporters describe severity; let the people who plan the work set priority.
The template
Title: <what goes wrong, where, in under ten words>
Environment: <app version or build> · <device> · <OS and version>
<browser and version> · <account or role> · <live / test>
Steps to reproduce:
1. <starting point the reader can reach>
2. <action, with the exact values used>
3. <action>
How often: <every time / sometimes (x in y tries) / once>
Expected: <what should have happened>
Actual: <what happened instead, exact text of any error>
Evidence: <screenshot, recording, log line, time it happened>
Severity: <data lost / main task blocked / workaround exists / cosmetic>
Workaround: <if there is one>
Notes: <anything else; guesses about the cause labelled as guesses>A bad report, rewritten
Title: Booking broken!! Customers can't book. Please fix ASAP. I think it's the new update.
Everything in it may be true, and none of it can be acted on. Which customers? Book what? Broken how? Since when? The rewrite takes five minutes and usually answers the question the fixer would have asked first:
Title: Booking form rejects dates in November with "Invalid date"
Environment: Live site, version 2.8.1 · iPhone 14, iOS 18 · Safari
Also on Windows 11, Chrome 128 · signed out
Steps to reproduce:
1. Open /book
2. Choose "Consultation", pick 12 November, 10:00
3. Enter name and email, press Book
How often: every time for any November date; October dates work
Expected: Confirmation page, and a confirmation email
Actual: Red message under the date: "Invalid date". Nothing sent.
Evidence: Screenshot attached. Three customers emailed about it
since Monday morning.
Severity: Main task blocked for November bookings. No workaround
except booking by phone.
Notes: Started after Monday's release (guess, not confirmed).Three short examples
Title: App closes when attaching a photo larger than 20 MB
Env: Android 15, Pixel 8, app 4.2.0 (build 311)
Steps: 1. Open any job 2. Attach 3. Choose a 24 MB photo
How often: every time; a 5 MB photo works
Expected: Photo attached, or a message that it is too large
Actual: App closes with no message
Severity: Workaround exists (shrink the photo first)Title: GET /v2/orders returns 500 when status=cancelled
Env: Staging, API 2026.09.3, service account with read scope
Steps: curl -H "Authorization: Bearer <token>" \
"https://staging.example.com/v2/orders?status=cancelled"
How often: every time; status=paid returns 200
Expected: 200 with the cancelled orders
Actual: 500 {"error":"internal"} at 09:14 UTC, request id in log
Severity: Main task blocked for the refunds screenTitle: Room 3 shows as free when it is already booked Env: Shared booking sheet, week tab for 6 October Steps: 1. Book Room 3, Tuesday 14:00 2. Open the Room view Expected: Room 3 marked busy on Tuesday 14:00 Actual: Still shows free; two teams arrived at once last week Severity: Workaround exists (check the week tab, not the Room view)
A version an AI assistant can act on
An AI agent fixing a bug works from what the report says and fills any gap with a guess. The template above already removes most gaps. Add three lines and it becomes an instruction an agent can follow from start to finish:
- Where: the file and function, the screen or the endpoint, if you know it. It saves the agent searching.
- Fixed when: one line saying how everyone will know. Usually a test that reproduces the bug and then passes, plus the check that must still pass.
- Do not: what the fix must not touch, such as “do not change the date format stored in the database”.
Where: src/booking/validateDate.ts; the /book form
Steps: as above; November dates fail, October dates pass
Expected: Any future date inside the booking window is accepted
Actual: "Invalid date" for every November date
Fixed when: A test booking 12 November fails before the fix and
passes after; the existing booking tests still pass
Do not: Change how dates are stored or the email template
Guess: Month numbering off by one (unconfirmed)Ask the agent to reproduce the bug before it changes anything, and to say so if it cannot. How agents should file bugs they notice, search for duplicates first and leave triage to people is covered in an issue tracker for AI agents; the wider template for any card an agent works from is in giving an AI agent a task it can finish.
Reports from outside the team
Customers, clients and testers outside the team will not fill in eight fields, and should not have to. Ask them four questions and collect the rest yourself.
What were you trying to do? What did you expect to happen? What happened instead? Can you add a screenshot? (optional)
- Collect the environment for them. If the form is in your app, record the version, device and browser automatically rather than asking.
- If your project lives on a code host, a structured form helps. GitHub’s issue forms (opens in a new tab), for example, are YAML files in
.github/ISSUE_TEMPLATEwith text fields, dropdowns and checkboxes, and the answers become the issue body. - Thank them and tell them what happens next. A reporter who hears nothing stops reporting.
- Security problems do not go on a shared list. Publish a private route for them; RFC 9116 (opens in a new tab) defines a
security.txtfile at/.well-known/security.txtthat tells researchers how to reach you. - Someone on the team turns the short report into a full one: tries the steps, writes the environment down, sets the severity. That is triage, not extra work; it happens either way.
On a fenbs board
On fenbs a bug is a task of kind bug, with a ref such as BUG-046. The report goes in the task’s note, which is written once and kept; a screenshot can be pasted straight into the task as a file. Priority runs from 1 to 10, 1 the most urgent. There is no separate severity field, so write severity as a line in the note, as the template does, and set priority when the bug is triaged. The plan field holds how it will be fixed, and the Testing section records what was checked once it is: Tested, Partly tested, Failed or Needs owner check, with notes. A person moves it to Completed.
For reporters outside the team, roles on a team board are defined by your company: give them one that can create tasks and comment but not move tasks between lanes, so what they file arrives under their own name and triage stays with you. Whoever files a task follows it automatically and gets an email when it moves or someone comments, which answers most “any news on this?” questions without anyone writing them.
Related
Start from the bug tracker template. For how bugs, features and enhancements divide up, see features, enhancements and bugs, and for what counts as fixed across the whole team, see definition of done examples and acceptance criteria vs definition of done.