QA strategy

Bug report template: what to include, with GitHub and Jira versions

A bug report template with a filled example, a GitHub issue form and a Jira field map, plus why each field matters and the mistakes that waste developer time.

A good bug report template asks for ten things: a title that states the symptom, the environment and build, steps to reproduce, the expected result, the actual result, severity, priority, evidence (screenshots, video, logs or a Playwright trace), how often it happens, and any workaround. Each field answers a question the developer would otherwise have to ask, and every question that waits for an answer delays the fix.

How to write a good bug report, field by field

Mozilla’s Bug Writing Guidelines call steps to reproduce “the most important part of any bug report”. The other fields make those steps work on someone else’s machine, or help the team decide when to fix it.

A title that states the symptom

The title is what a triager sees first, and in a list it may be all they read. Say what goes wrong and when, not the area or your guess at the fix. Mozilla suggests about 10 words that explain “the problem, not your suggested solution”.

  • Weak: “Checkout broken”
  • Strong: “Checkout drops promo discount when shipping country changes”

Environment and build

A bug that happens only on staging, only in Safari or only for admins stays invisible to a developer who tries it elsewhere. Write down where you saw it, the build or commit, the browser and OS with versions (or the device, OS and app version on mobile), and the account: role, plan, feature flags, language and time zone. Mozilla asks for the earliest version that shows the bug, because it points to the change that introduced it. If your app does not show its build anywhere, add it to the footer.

Steps to reproduce

  1. Start from a known state. “Sign in as a customer with an empty cart” beats “go to checkout”.
  2. One action per step, with the exact values you used.
  3. Cut every step that does not change the outcome.
  4. Add the API call if you have it. It shows whether the backend or the screen is wrong.

Expected and actual result

Expected is what should have happened and where that comes from: the spec, the ticket or the previous release. Actual is what you saw, with error messages copied as text. If nobody can say what was expected, you have a question for the product owner, not a bug.

Severity versus priority

The ISTQB glossary defines severity as “the degree of impact that a defect has on the development, testing or operation of a component or system” and priority as “the level of importance assigned to a task according to specific criteria”. The reporter proposes severity from the impact; whoever owns the backlog sets priority from timing and business context. A typo in the product name the day before a launch is low severity and high priority. A crash in a yearly report with a workaround can be high severity and still wait. Write the scale down once:

Level Impact Example
S1 critical Data loss, security, payments fail, main flow blocked Nobody can pay
S2 major Main flow wrong, with a workaround Discount lost, reapplying works
S3 minor Secondary flow broken Export misses a column
S4 cosmetic Looks wrong, still works Misaligned button

Then agree which levels block a release, as our Go/No-Go release checklist suggests.

Evidence: screenshots, video, logs and a Playwright trace

  • Screenshots with the URL visible and the wrong value marked.
  • Video for multistep or timing problems, noting when the bug appears.
  • Console errors and the failing request (method, path, status code, response body), pasted as text.
  • The request ID and the time with time zone, to find the server log line.
  • A Playwright trace if an automated test found the bug.

A trace holds every action with DOM snapshots before and after it, the browser console, and each network request with its headers and bodies. Open it with npx playwright show-trace trace.zip or on trace.playwright.dev, which loads it entirely in your browser. Tracing every test is “performance heavy”, so Playwright’s docs recommend trace: 'on-first-retry' on CI with retries turned on, or trace: 'retain-on-failure' without retries. A trace stores request headers, which can include session cookies: use test accounts, and think twice before attaching one to a public issue.

Frequency and workaround

Say whether it happens every time, sometimes or once, as Mozilla asks, and give an intermittent bug a count (“2 of 5 attempts”). If an automated test fails only sometimes, the test itself may be unreliable; our guide to flaky tests in Playwright covers how to find the cause. Then write how users can still get the job done, or “none known”. A workaround can lower the priority.

A bug report example

A filled example for a made up online shop:

Title: Checkout drops promo discount when shipping country changes

## Environment

- Where: staging, https://staging.shop.example/checkout
- Build: web 2026.10.17.1 (commit 8c41d2e); production 2026.10.15.2 not affected
- Browser: Chrome 155 on Windows 11 (not tried on Safari or Firefox)
- Account: buyer@test.example, customer role, default feature flags

## Steps to reproduce

1. Sign in as buyer@test.example with an empty cart.
2. Add "Canvas tote" (49.00 USD) to the cart and open /checkout.
3. Apply promo code SAVE10. The total shows 44.10 USD before shipping.
4. Change Shipping country from United States to Canada.

## Expected result

The 10% discount stays applied (promo rules, ticket SHOP-212).

## Actual result

The "SAVE10 applied" badge stays, but the discount line disappears and the
total goes back to 49.00 USD plus shipping. Paying charges the full amount.

## Severity and priority

- Severity: S2, wrong total in checkout; applying the code again works
- Priority: proposed P1, the SAVE10 email goes out on Monday

## Frequency

Every time (5 of 5 attempts)

## Evidence

- Video: promo-country.webm (bug at 0:25), screenshots before and after
- Network: POST /api/checkout/shipping returned 200 with "discount": 0
- Server log: request ID 9f3a61c2, 14:32 UTC+7
- Playwright trace: trace.zip from checkout/promo.spec.ts

## Workaround

Apply the promo code again after changing the country.

## Notes

Suspect, not verified: the shipping update rebuilds the cart without the code.

The bug report template (Markdown)

Copy it into a GitHub issue, a Jira description or a chat message. On GitHub you can also save it in .github/ISSUE_TEMPLATE/ with a short YAML header, as in GitHub’s own example (name, about, title, labels, assignees).

Title: <what goes wrong> when <trigger>

## Environment

- Where: <production | staging | preview URL>
- Build: <version or commit>; last good build: <if known>
- Browser and OS: <versions> (mobile: <device, OS and app version>)
- Account: <role, plan, feature flags, language, time zone>

## Steps to reproduce

1. <starting state: who is signed in, what data exists>
2. <one action per step, with exact values>

## Expected result

<what should happen, and the spec or ticket that says so>

## Actual result

<what happened, error messages copied exactly>

## Severity and priority

- Severity: <S1 | S2 | S3 | S4>, <impact>
- Priority: <set in triage, or proposed with a reason>

## Frequency

<every time | x of y attempts | once>

## Evidence

<screenshots, video with timestamp, console errors, failing request,
request ID and time, Playwright trace>

## Workaround

<how users can still get it done, or "none known">

## Notes

<related issues, recent changes; label guesses "not verified">

A GitHub issue form for bug reports

A Markdown template prefills the issue body, and the reporter can delete any of it. An issue form is a YAML file that GitHub renders as a web form with text fields, dropdowns, checkboxes and file uploads, then turns the answers into Markdown in the issue. As of October 2026, GitHub’s docs still call issue forms a public preview. Save this as .github/ISSUE_TEMPLATE/bug_report.yml on the default branch; it uses only documented keys:

name: Bug report
description: Something in the product does not work as it should.
labels: ['bug', 'triage']
body:
  - type: markdown
    attributes:
      value: One bug per report. Remove tokens and customer data from evidence first.
  - type: input
    id: environment
    attributes:
      label: Environment and build
      description: Where, build or commit, browser and OS, account role.
      placeholder: 'staging, build 2026.10.17.1, Chrome 155 on Windows 11, customer'
    validations:
      required: true
  - type: textarea
    id: steps
    attributes:
      label: Steps to reproduce
      description: Start from a known state, one action per step.
      value: |
        1.
        2.
        3.
    validations:
      required: true
  - type: textarea
    id: expected
    attributes:
      label: Expected result
      description: And the spec or ticket that says so.
    validations:
      required: true
  - type: textarea
    id: actual
    attributes:
      label: Actual result
      description: Copy error messages exactly.
    validations:
      required: true
  - type: dropdown
    id: severity
    attributes:
      label: Severity
      description: Impact on users. Priority is set in triage.
      options:
        - 'S1: data loss, security, payments fail, or a main flow blocked'
        - 'S2: a main flow broken or wrong, with a workaround'
        - 'S3: a secondary flow broken'
        - 'S4: cosmetic'
    validations:
      required: true
  - type: dropdown
    id: frequency
    attributes:
      label: Frequency
      options:
        - Every time
        - Sometimes (write how often below)
        - Once, could not reproduce
    validations:
      required: true
  - type: upload
    id: evidence
    attributes:
      label: Evidence
      description: Screenshot, video or Playwright trace (trace.zip).
    validations:
      required: false
      accept: '.png,.jpg,.gif,.webp,.mp4,.mov,.webm,.zip,.log,.txt,.json'
  - type: textarea
    id: logs
    attributes:
      label: Logs
      description: Console errors, failed requests, server lines with the request ID.
      render: shell
  - type: textarea
    id: workaround
    attributes:
      label: Workaround and notes
      description: How users can still get it done. Label guesses as not verified.

Before you rely on it:

  • required is enforced only in public repositories. In a private one, catch empty answers in triage.
  • Labels must already exist, so create triage first.
  • Uploads take up to 10 MB per image, 100 MB per video and 25 MB for a zipped trace.
  • No blank issues: set blank_issues_enabled: false in .github/ISSUE_TEMPLATE/config.yml. People with write access still see a blank option, marked Maintainers only.
  • Forbidden words: GitHub refuses input and textarea labels with words such as “password”.

Mapping the template onto Jira fields

Jira software spaces come with a Bug work type, and most of the template has a standard field. Atlassian is renaming “issues” to “work items” and “projects” to “spaces”, so you will meet both terms.

Template Jira field Standard or custom
Title Summary Standard
Environment Environment Standard
Build Affects versions Standard, if you track versions
Steps, expected, actual Description, as headings Standard
Severity Severity, a select list Custom
Priority Priority Standard
Evidence Attachment Standard
Frequency, workaround Text or select fields, or Description Custom
Area Components or Labels Standard

From Atlassian’s docs:

  • Environment is a text field you can search with JQL, for example environment ~ "Safari".
  • Priority ships with Highest, High, Medium, Low and Lowest, and admins can change them.
  • Attachments are on by default, up to 1 GB per file (2 GB at most). To attach files while creating a bug, the Attachment field must not be hidden in that work type’s field configuration.
  • Severity, Frequency and Workaround are custom fields that a Jira admin creates (a single choice select list, a paragraph or a short text field) and adds to a field configuration.

Start with steps and results as headings in Description, and give severity its own field so triage can filter by it.

Common mistakes that waste a developer’s time

  1. A title that names the area. “Checkout issue” could be a typo or an outage.
  2. Steps that start in the middle, skipping the account, data and flags.
  3. “It doesn’t work” as the actual result, instead of the error text and the status code.
  4. No expected result, so the developer has to guess whether it is a bug or a decision.
  5. Several bugs in one report. Mozilla asks for one report per issue; a shared ticket closed after the first fix hides the second.
  6. A theory written as a fact. Mozilla asks reporters to “clearly separate facts (observations) from speculations”; “the cache is broken” sends someone to the cache.
  7. Evidence nobody can search: a photo of a screen, a log pasted as an image, a 5-minute video with no timestamp.
  8. Severity used to get attention. If every bug is critical, real emergencies wait in the same queue.
  9. Secrets in the evidence: tokens in logs, customer data in screenshots, cookies in traces.
  10. A report that lives only in chat. File it in the tracker and post the link.

How we report bugs

Every bug we send comes with steps to reproduce, expected and actual results, and evidence such as screenshots, video or logs. Claude agents run the suites and collect evidence for each failure; a QA engineer looks at every failure before it becomes a bug report or a test fix and confirms each bug and its severity. Your developers fix it. Our open-source sample project shows the rules in code: each bug is reproduced three times, through the API before the UI, and pinned by a test marked as an expected failure, which turns red the day the bug is fixed. How it works shows a normal week with us.

Sources

Researched and drafted with Claude, Anthropic's AI model, and checked against the sources it links. Spotted an error? Tell us and we will correct it.

Keep reading

Every post

Bug reports your developers can act on

A QA engineer confirms every failure before it becomes a bug report, and each report comes with steps to reproduce, expected and actual results, and evidence such as screenshots, video or logs.

Or write to qa@releaseworthy.app. Still deciding after the proposal? We book a Google Meet call for your questions.