How to write a good bug report (with logs and stack traces that help)
Write bug reports maintainers can act on: a searchable title, minimal reproduction, expected vs actual behavior, the right logs, and a copyable template.
WorkflowBy the Codeshot team6 min read
Quick answer: A good bug report has a specific, searchable title; a minimal set of steps that reproduces the problem; what you expected versus what actually happened; the relevant slice of the error log or stack trace as text; exact versions of everything involved; and what you have already tried. The goal is to let someone else see the bug on their own machine in under five minutes.
Maintainers triage bug reports the way emergency rooms triage patients: the clearer the symptoms, the faster the treatment. "It's broken, see screenshot" waits in the queue. A report with a minimal reproduction, the exact error and the environment often gets fixed the same day — sometimes by another contributor, because the report already did half the debugging.
Simon Tatham's classic essay How to Report Bugs Effectively summed it up decades ago: the aim of a bug report is to enable the programmer to see the program failing in front of them. Everything below serves that aim.
The anatomy of a good bug report
- A specific, searchable title
- A one-paragraph summary
- Steps to reproduce, ideally a minimal reproduction
- Expected behavior versus actual behavior
- The relevant error output — logs, stack trace, failing test
- The environment — versions, operating system, configuration
- What you already tried, including workarounds
Write a title someone can search for
The title decides whether a maintainer opens the issue and whether the next person with the same problem finds it. Include the component, the action and the symptom — and the version if you know it.
| Weak title | Strong title |
|---|---|
| Login broken | OAuth callback returns 500 when the email contains "+" (v3.2.0) |
| App crashes | Crash on startup when config.yaml has an empty plugins list |
| Doesn't work on Safari | Date picker ignores keyboard input in Safari 18 |
If there is a distinctive error message, include a short, exact excerpt. People search for error messages word for word.
Reduce it to a minimal reproduction
A minimal reproducible example is the smallest program, configuration or sequence of steps that still shows the bug. It is the single most valuable part of a report — and building one often reveals that the problem is in your own code, which saves everyone time.
How to minimize:
- Start from a fresh project, or a template the maintainers provide.
- Add only what is needed to trigger the bug: remove styling, unrelated routes and extra dependencies.
- Replace real data with the smallest input that still fails.
- Keep removing things until the bug disappears, then put back the last thing you removed.
Share the result as a repository, an online sandbox or a short code block, with numbered steps:
1. git clone https://github.com/your-name/repro-oauth-plus
2. npm install
3. npm run dev
4. Sign in with an account whose email is ada+test@example.com
5. Observe HTTP 500 on /auth/callback
If you cannot isolate it, say so and describe how often it happens: "about one in five page loads, only in production" is still useful information.
Separate what you expected from what happened
Write two short, separate sentences. This sounds obvious, but it is where many reports become ambiguous. Sometimes the reporter's expectation is the actual bug — and a maintainer can only tell if it is written down.
Expected: the user is redirected to
/dashboard.Actual: the callback returns HTTP 500 and the server logs
TypeError: Cannot read properties of undefined (reading 'split').
Include the right part of the logs
Most reports get this wrong in one of two ways: too little (a cropped image of the last line) or far too much (ten thousand lines of debug output).
- Start a little before the failure. The 5–10 lines leading up to an error often explain it: a retry, a warning, a configuration value being loaded.
- Include the first error, not just the last. Later errors are usually consequences of the first one.
- Include the complete stack trace of that error, not just its top line.
- Trim repetition and say so:
[… 240 identical retry lines omitted …]. - Redact before you post. Logs are full of tokens, cookies, emails and internal hostnames — see how to redact secrets in screenshots.
How to read a stack trace before you paste it
A stack trace lists the chain of function calls that led to an error. Reading it first lets you point the maintainer to the right place.
- Order differs by language. JavaScript, Java and Go list the most recent call first (at the top). Python's traceback says "most recent call last" and puts it at the bottom.
- Find the boundary between library code and your code. The last frame in your code is usually where the bad input came from; the first frame in the library is what received it. Mention both.
- In Java and other JVM languages, read the last "Caused by:" section. That is usually the root cause; the exceptions above it are wrappers.
- Watch for truncated traces. Node.js keeps only the 10 most recent frames by default; run with
node --stack-trace-limit=50 app.jsto see more.
TypeError: Cannot read properties of undefined (reading 'split')
at parseEmail (src/auth/email.ts:12:23) ← the failing line
at handleCallback (src/auth/callback.ts:41:17) ← your code calling it
at Layer.handle (node_modules/express/lib/router/layer.js:95:5)
Paste logs as text first, images second
Always include logs as text in a fenced code block, so they are searchable and copyable:
```text
2026-10-21T09:14:03Z INFO auth callback received state=ok
2026-10-21T09:14:03Z ERROR auth TypeError: Cannot read properties of undefined (reading 'split')
```
An image is a useful addition when it makes the problem easier to see — a color-coded log where the ERROR line stands out from INFO noise, or a test run showing which cases fail. The error and log image tool and the test results generator are made for this. The text should still be there for searching and copying.
List the environment precisely
Use version numbers, never "latest":
- The library or app version — and whether the bug still happens on the newest release.
- The runtime: Node.js, Python, Java, the browser — with versions.
- The operating system and architecture, such as macOS 15 on Apple silicon or Ubuntu 24.04 on x86-64.
- Relevant configuration, feature flags and environment (development, staging, production).
Many ecosystems can print this for you: npx envinfo for JavaScript projects, python -m pip freeze for Python dependencies, flutter doctor -v for Flutter, rustc -vV for Rust.
Say what you already tried
"Clearing the cache didn't help; downgrading to 3.1.4 fixes it" is gold. A known-good version lets the maintainer run git bisect and find the exact commit that introduced the bug. If you found a workaround, share it — other users can use it while the fix is in progress.
Include a failing test when you can
A failing test is the most precise reproduction there is. If you can write one against the project's own test suite, include the test and its output. The pass/fail summary shows at a glance which cases break and which still work, and the test can be merged with the fix to prevent regressions.
Bug report etiquette that gets issues fixed
- Search existing issues — including closed ones — before filing.
- Report one bug per issue.
- Follow the project's issue template; it exists because the maintainers need those fields.
- Answer follow-up questions, and close the issue yourself if it turns out to be your mistake.
- Report security vulnerabilities privately, following the project's
SECURITY.md, never in a public issue. - Be kind. Most open-source maintainers are volunteers.
A copyable bug report template
## Summary
One paragraph describing the problem.
## Steps to reproduce
1.
2.
3.
## Expected behavior
## Actual behavior
## Logs / stack trace
```text
Relevant slice, with secrets redacted
```
## Environment
- Version:
- Runtime:
- OS:
## What I tried
For a multi-step reproduction, the terminal session tool can turn the commands and their output into a single image to accompany the text.
Frequently asked questions
What should a bug report include?
A specific title, a summary, steps to reproduce, expected versus actual behavior, the relevant logs or stack trace as text, exact versions of the software and environment, and anything you already tried.
What is a minimal reproducible example?
It is the smallest amount of code, configuration and steps that still demonstrates the bug. Removing everything unrelated makes the cause easier to find and often reveals whether the problem is in the library or in your own code.
Should I include screenshots in a bug report?
Include screenshots for visual problems, and optionally a styled image of a log or test run to make the failure obvious. Always include error messages and logs as text too, so they can be searched and copied.
How much of the log should I include?
Include about 5–10 lines before the first error, the complete stack trace of that first error, and any warnings that appear just before it. Trim long repetitive sections and note that you did.