- Tutorial
- Bug reporting
- Product
How to write a bug report that gets fixed
A fixable bug report has a specific title, numbered repro steps, expected‑versus‑actual, and evidence attached. A paste‑able template, plus what separates a report from a complaint.
The fastest way to get a bug fixed is to write the report the fixer can act on without asking you anything. Most bug reports read like complaints — “it’s broken, again” — and complaints wait in the queue. This post is the structure of a report that moves: what goes in it, in what order, and where the recording and the screenshot fit.
The title is the triage
A maintainer sorts a queue by titles. “Login broken” could be ten bugs; “401 loop on login when SSO certificate expires” is one bug with a suspect attached. The formula is behavior plus condition: what happens, and when exactly it happens. If you can’t write a specific title yet, you don’t understand the bug well enough to file it — which is useful information, because it means the repro isn’t pinned down.
The body, in this order
Fixers read reports in a predictable order, so give them the parts in that order:
- Expected: what should happen, in one sentence.
- Actual: what happens instead, in one sentence.
- Repro steps: numbered, from a cold start — every step someone else wouldn’t guess. “Log in, open Settings, click Export twice quickly” beats “export doesn’t work.” If it’s intermittent, say how often it fires and what you’ve seen correlate with it.
- Environment: app version, macOS version, machine. A bug on macOS 15 that can’t reproduce on macOS 26 is a different bug.
- Evidence: the recording, the screenshot, the logs — attached, not described.
The screen‑recording version of this list covers what the evidence should contain; this post is about the words around it. The two work together: the recording proves the repro, the steps let someone else run it without re‑watching the whole video.
What separates a report from a complaint
Three things, and they’re all checkable:
- A stranger could follow it. Every step from launch, no “my settings,” no “like usual.”
- One bug per report. Two bugs in one ticket means both wait on the slower one.
- The severity is claimed, not implied. “This loses data” and “this is ugly” route to very different queues — say which one you’re filing.
A template to paste
Title: <behavior> when <condition>
Expected: <one sentence>
Actual: <one sentence>
Steps:
1. <cold start>
2. <action>
3. <action that triggers it>
Environment: <app version>, <macOS version>, <machine>
Evidence: <recording / screenshot / logs — attached>
Notes: <frequency if intermittent, anything you ruled out>
Fill it from the recording, not from memory: play the take back and write the steps as you watch them happen. Memory writes confident, wrong repro steps; the recording writes right ones.
The fast path
The honest note: I make Snapbak, which exists because this checklist is tedious by hand. Record the bug and the report drafts itself — repro steps from the captured clicks, the console errors and failed requests attached through the browser extension, the screenshot redacted on the device before it leaves. The template above still applies; the app just fills it while you think about the actual bug.
Snapbak is free for the first 100 users: download it, file your next bug with the recording attached, and time the difference.