Skip to content

A good bug report lets someone else reproduce the bug without asking you anything. The template below covers what a developer needs to do that for a web app. Copy it into your issue tracker, a chat message or a document, and fill in each field.

## Title
[Where] [what goes wrong] [when]
## Steps to reproduce
1.
2.
3.
## Expected result
What should have happened.
## Actual result
What happened instead.
## Environment
URL, browser, operating system

Use this for small bugs; use the full template below when the bug is intermittent, affects money or data, or comes from a customer.

## Title
[Where] [what goes wrong] [when]
## Summary
One or two sentences on what is broken and who it affects.
## Steps to reproduce
1.
2.
3.
## Expected result
What should have happened.
## Actual result
What happened instead. Quote any error message exactly.
## Environment
- URL:
- Browser and version:
- Operating system:
- Screen or window size:
- Account or role:
## Frequency
Always / Sometimes / Once
## Console errors
Paste the red lines from the browser console, with their stack.
## Failed network requests
- Method and URL:
- Status:
- Response body:
## Screenshot or recording
Link:
## Severity and impact
Who is blocked, and is there a workaround?
  • Search the tracker first. If someone has already reported the bug, add your steps, environment and evidence to that report rather than filing a duplicate.
  • One bug per report. Separate bugs get fixed and closed separately, so two problems in one report means one of them gets lost.
  • Try a private window with extensions off. An incognito or private window rules out cache, cookies and browser extensions as the cause.

Title. Say where the bug is, what goes wrong and when. A developer should know which part of the app to open from the title alone.

  • Bad: “Checkout broken”
  • Good: “Checkout: Pay button does nothing after applying a coupon”

Summary. One or two sentences in plain words. Say who is affected if you know: every user, one account, only admins.

Steps to reproduce. Number every step, starting from a page anyone can open. Include what you typed and what you clicked, in order. Leave nothing out because it seems obvious.

  • Bad: “Try to check out with a coupon, it fails.”
  • Good:
    1. Sign in as a customer and add any item to the cart.
    2. Go to /checkout.
    3. Enter the coupon SPRING10 and click Apply.
    4. Click Pay.

Expected result. What the app should have done, such as “the payment form submits and the order confirmation opens”. This stops a developer from fixing the wrong thing.

Actual result. What you saw instead. Copy error messages word for word. “Nothing happens” is a useful answer when nothing happens.

Environment. The page’s full URL, the browser and its version (in Chrome, open chrome://version), the operating system, the window size, and the account or role you used. The free browser and screen checker copies the browser, system and sizes as one block. Many bugs only show for one browser, one screen size or one kind of account.

Frequency. Always, sometimes or once. A bug that happens sometimes points to timing, caching or data, and the developer will look in different places.

Console errors. The errors the page logged. These often name the cause directly. See the two fields people skip.

Failed network requests. Requests that returned an error status or never finished. The method, URL, status and response body are usually enough to tell a frontend bug from a backend one.

Screenshot or recording. A picture shows the state of the page. A video shows the order of events, which a picture can’t.

Severity and impact. Who is blocked and whether there is a workaround. This decides how soon it gets fixed, so be honest about it.

This is an invented bug in an invented shop, to show the fields in use.

## Title
Checkout: Pay button does nothing after applying a coupon
## Summary
After a valid coupon is applied, clicking Pay does nothing. Customers who use a coupon can't place an order.
## Steps to reproduce
1. Sign in as a customer and add any item to the cart.
2. Go to https://shop.example.com/checkout.
3. Enter the coupon SPRING10 and click Apply. The discount shows.
4. Click Pay.
## Expected result
The payment is submitted and the order confirmation page opens.
## Actual result
Nothing happens. The button stays enabled and no message appears.
## Environment
- URL: https://shop.example.com/checkout
- Browser and version: Chrome (latest stable)
- Operating system: macOS
- Screen or window size: 1440 × 900
- Account or role: customer account, no saved card
## Frequency
Always, when a coupon is applied. Without a coupon, Pay works.
## Console errors
Uncaught TypeError: Cannot read properties of undefined (reading 'amount')
at submitPayment (checkout.js:212:31)
## Failed network requests
- Method and URL: POST /api/orders
- Status: 422
- Response body: {"error":"discount.amount is required"}
## Screenshot or recording
Link: (recording of steps 1 to 4)
## Severity and impact
High. Every order with a coupon fails. Workaround: remove the coupon.

With the console error and the failed request, a developer can start at submitPayment and the coupon payload instead of trying to reproduce the bug first.

These are invented too, including every number in them. Each one shows a different kind of evidence doing the work.

A layout bug. The window size and the fresh session are what make it reproducible.

## Title
Settings: Save button hidden behind cookie banner on 1366 × 768
## Steps to reproduce
1. Open https://app.example.com/settings in a private window, so the cookie banner shows.
2. Change any field and scroll to the bottom.
## Expected result
The Save button is visible and can be clicked.
## Actual result
The cookie banner covers the Save button. Clicking it hits the banner instead.
## Environment
- URL: https://app.example.com/settings
- Browser: Chrome (latest stable), window 1366 × 768
- Operating system: Windows
- Not seen at 1440 × 900 or wider, or after the banner is dismissed.

A slow page. The network timing shows where the time goes, so the developer starts on the server, not the page.

## Title
Reports page takes ~12 s to load for accounts with many projects
## Steps to reproduce
1. Sign in to an account with 200+ projects.
2. Open https://app.example.com/reports.
## Expected result
The page loads in a second or two, as it does for small accounts.
## Actual result
A spinner shows for about 12 seconds before the table appears.
## Network
- GET /api/reports?include=projects: 200, 11.8 s total, 11.6 s waiting for the server, 4.2 MB response
- Same request on an account with 3 projects: 200, 0.4 s
## Environment
- Browser: Chrome (latest stable), Operating system: macOS
- Frequency: Always, for large accounts

A server error. The method, URL, status and response body point straight at the backend.

## Title
Upload avatar: 500 error for PNG files over 2 MB
## Steps to reproduce
1. Go to https://app.example.com/profile.
2. Click Change avatar and choose a PNG file of 2.4 MB.
## Expected result
The new avatar is saved and shown.
## Actual result
"Something went wrong" appears and the old avatar stays.
## Failed network requests
- Method and URL: POST /api/users/me/avatar
- Status: 500
- Response body: {"error":"internal_error","request_id":"req_8f2c1a"}
## Notes
A 1.8 MB PNG and a 3 MB JPEG both upload fine. Always happens.

The two fields people skip: console and network

Section titled “The two fields people skip: console and network”

Most reports leave out the console and the network. They are the fields that save the most time, and the hardest ones for someone who isn’t a developer to fill in. Asking a customer to “press F12 and open the Network tab” rarely works.

  1. On the page with the bug, press F12, or Ctrl+Shift+J (Cmd+Option+J on a Mac), to open DevTools on the Console tab.
  2. Reproduce the bug with DevTools open.
  3. Click the red error to expand its stack.
  4. Select the error and its stack and copy them, or right-click in the console and choose Save as… to save the whole log as a file.

A HAR file holds every request the page made, with headers and bodies.

  1. Open DevTools and go to the Network tab.
  2. Tick Preserve log, so requests survive a page change.
  3. Reproduce the bug.
  4. Click the download arrow in the Network toolbar (Export HAR), or right-click a request and choose to save all as HAR, then attach the file to the report.

See What is a HAR file? for every browser and how to clean one before sharing.

The template in Jira, GitHub Issues and Linear

Section titled “The template in Jira, GitHub Issues and Linear”

The fields stay the same in every tool. Only where they go changes.

Jira. Create an issue of type Bug. The title goes in Summary. Steps, expected, actual, console and network go in Description. Use the Environment field if your project has it, otherwise keep that section in the description. Set Priority from severity, and attach the screenshot, recording or HAR file.

GitHub Issues. Paste the template as the issue body, which renders as Markdown, and add a bug label. To give everyone the same form, save it in your repository as .github/ISSUE_TEMPLATE/bug_report.md with a short header:

---
name: Bug report
about: Something in the app doesn't work
labels: bug
---

Then paste the template below the header. For a structured form instead of a Markdown body, use the issue form below.

Linear. The title goes in the issue title and the rest in the description, which takes Markdown. Add a Bug label and set the priority from severity. Linear also has issue templates in the team’s settings, where you can save this one.

GitHub issue forms live at .github/ISSUE_TEMPLATE/bug_report.yml. Instead of a Markdown body to edit, reporters get a form with labelled fields, dropdowns and required answers, and GitHub turns their answers into the issue body. Save this file in your repository as it is, or trim the fields you don’t need.

name: Bug report
description: Something in the app doesn't work
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for reporting a bug. Please search existing issues first, and file one bug per report.
- type: input
id: summary
attributes:
label: Summary
description: Where the bug is, what goes wrong and when.
placeholder: "Checkout: Pay button does nothing after applying a coupon"
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: Number every step, starting from a page anyone can open.
value: |
1.
2.
3.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected result
description: What should have happened.
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual result
description: What happened instead. Quote any error message exactly.
validations:
required: true
- type: input
id: url
attributes:
label: URL
placeholder: https://
- type: dropdown
id: browser
attributes:
label: Browser
options:
- Chrome
- Edge
- Firefox
- Safari
- Other
- type: input
id: os
attributes:
label: Operating system
placeholder: macOS, Windows, Linux
- type: dropdown
id: frequency
attributes:
label: Frequency
options:
- Always
- Sometimes
- Once
- type: textarea
id: console
attributes:
label: Console errors
description: Paste the red lines from the browser console, with their stack.
render: shell
- type: textarea
id: network
attributes:
label: Failed network requests
description: Method and URL, status, and response body.
- type: input
id: recording
attributes:
label: Screenshot or recording link
- type: dropdown
id: severity
attributes:
label: Severity
description: Who is blocked, and is there a workaround?
options:
- Blocker (no workaround)
- Major (workaround exists)
- Minor (cosmetic or rare)

The browser dropdown is the reporter’s browser. Add or remove options to match the browsers your app supports.

The template asks a reporter to collect what the browser already knows. Faylee collects it for them.

With Faylee’s Chrome extension, which also works in Edge, Brave and Arc, you record the tab or screen while you show the bug, or save an instant replay of the last few minutes after it already happened. One link then carries:

  • The video, or for an instant replay, a replay of the page.
  • The console, with errors and their stacks.
  • Every network request with its headers and bodies.
  • The steps to reproduce, from your clicks, typing and page changes.
  • The browser, system and window size.
  • A DOM replay of the page you can inspect at any moment.

A developer opens the link in the web viewer and reads the console and network next to the video. A coding agent such as Claude Code, Codex or Cursor can read the same report through Faylee’s MCP server and work on the fix there. Customers who don’t have the extension can send a screen recording through a recording link, with no install.

To try it, start free, or see pricing.

A clear title, numbered steps to reproduce, the expected and actual result, the environment (URL, browser, operating system, account), how often it happens, and any console errors and failed network requests. A screenshot or recording helps a developer see the order of events.

What’s the difference between a bug report and a feature request?

Section titled “What’s the difference between a bug report and a feature request?”

A bug report says the app doesn’t do what it is meant to do, and gives the steps to show it. A feature request asks for something the app was never meant to do. If you can’t name an expected result the app is supposed to give, it is probably a feature request.

How do I get console logs from a customer?

Section titled “How do I get console logs from a customer?”

You can walk them through opening DevTools and copying the errors, as in the steps above, though it often goes wrong. A browser extension that records the console with the bug does it without the customer touching DevTools.

Can I attach a bug report to Jira or Linear?

Section titled “Can I attach a bug report to Jira or Linear?”

Yes. Paste the template into the issue, as above. Faylee also files reports as issues in Linear, GitHub, Jira, GitLab, Azure DevOps, ClickUp, Notion, Asana and Trello, with the steps, errors, failed requests and environment drafted from the capture, and keeps comments in step both ways with most of them. See Integrations overview and Issue trackers.