Educational Blog

How to Write a Minimal Reproducible Bug Example

Learn how to reduce a confusing software bug to a small, repeatable example that helps others diagnose and fix it faster.

A minimal reproducible bug example is the smallest self-contained demonstration that reliably shows a software problem. Creating one helps you debug faster and gives teammates, maintainers, or support teams the information they need to reproduce the issue.

What a minimal reproducible example includes

A useful example usually contains four things:

  • Minimal: It removes unrelated code, files, dependencies, and configuration.
  • Reproducible: Another person can follow the same steps and see the same behavior.
  • Self-contained: It includes enough context to run without guessing.
  • Accurate: It demonstrates the actual bug rather than a simplified example that behaves differently.

The example does not need to be beautiful, production-ready, or architecturally representative. Its purpose is to isolate one failure. A ten-line script that consistently crashes is often more useful than a thousand-line application with many possible causes.

A minimal example should also distinguish between the expected result and the actual result. For example:

  • Expected: parseDate("2026-09-24") returns a date object.
  • Actual: The function returns null when the application runs in the Europe/Budapest time zone.

That distinction prevents people from spending time guessing what “wrong” means.

Step 1: Describe the bug precisely

Before deleting code, write a one- or two-sentence description of the problem. Avoid conclusions such as “the framework is broken” unless you have verified them. Describe observable behavior instead.

A strong description answers these questions:

  1. What action did you take?
  2. What did you expect to happen?
  3. What happened instead?
  4. How often does it happen?
  5. Which environment is involved?

For example:

When a form is submitted with an empty optional nickname field, the API returns HTTP 500 instead of creating the user. The problem occurs every time with version 4.2.1 of the application running on Node.js 22.

This is more actionable than:

User creation is broken after the latest update.

Record the exact error message, including capitalization, error code, and the first relevant lines of the stack trace. Do not rewrite an error in your own words if you can copy the original output.

Step 2: Confirm that the problem is real and repeatable

Run the same reproduction several times. If the result changes, identify what changes between attempts. A bug that occurs only occasionally may involve timing, concurrency, network conditions, caching, random values, or external services.

Create a short reproduction recipe with numbered steps:

  1. Start with a clean project or known application state.
  2. Install the listed dependency versions.
  3. Create the input or data needed for the test.
  4. Run the exact command.
  5. Record the output.

Keep the steps literal. “Configure the app normally” forces the reader to make assumptions. Instead, provide the relevant setting, command, or file content.

If the bug depends on existing data, determine the smallest data set that still triggers it. A database export containing thousands of records may hide the important condition. Try reducing it to one table, one row, or one request.

Check whether the issue is affected by:

  • Operating system and version
  • Runtime or language version
  • Package, browser, driver, or framework version
  • Locale and time zone
  • Environment variables
  • Input encoding
  • Network access
  • Account permissions
  • Database engine and version

You do not need to include every detail in the final example, but you should know which details matter.

Step 3: Make a copy and remove unrelated parts

Never simplify the only copy of a working project. Duplicate the relevant files or create a separate reproduction directory. Then remove anything that is not necessary to trigger the issue.

A practical reduction order is:

  1. Remove unused imports and packages.
  2. Delete unrelated routes, components, classes, and functions.
  3. Replace real user data with a few representative values.
  4. Remove styling, logging, and UI code that does not affect the failure.
  5. Replace external services with fixed local values when possible.
  6. Reduce multiple inputs to one input that still fails.
  7. Combine setup into a short, obvious script.

After each removal, run the reproduction again. If the bug disappears, restore the most recent change and test more carefully. This is a form of binary reduction: remove a large section, test, and narrow the search based on the result.

Do not remove the line that appears to cause the failure simply because it looks suspicious. The goal is to preserve the failure while reducing everything around it.

Step 4: Separate the bug from external systems

External systems make reproduction difficult. If your application calls a payment provider, cloud API, database, or internal service, try to replace that dependency with a deterministic substitute.

Useful alternatives include:

  • A hard-coded response matching the relevant API result
  • A local JSON fixture
  • A small mock server
  • An in-memory database
  • A temporary test account with non-sensitive data
  • A recorded request and response

For example, instead of asking someone to access your private API, include a short function that returns the response your code needs to process. This lets others investigate the parsing or business-logic problem without requiring credentials.

However, do not replace an external dependency if the dependency itself is the suspected cause. If the problem is an authentication failure from a third-party service, a mocked response may hide the issue. In that situation, provide a sanitized request, response status, relevant headers, API documentation version, and the smallest safe set of configuration details.

Step 5: Remove secrets and private information

Inspect every file before sharing it. Minimal examples often contain accidental secrets in configuration files, command history, logs, screenshots, or copied request headers.

Remove or replace:

  • API keys and access tokens
  • Passwords and session cookies
  • Private certificates and private keys
  • Personal names, email addresses, and phone numbers
  • Customer records and internal URLs
  • Proprietary source code unrelated to the issue
  • Database connection strings

Use clearly fake values such as example-token and user@example.test. Do not merely blur secrets in a screenshot if the original text remains in the uploaded file or image metadata.

When replacing private data, preserve the property that matters. If the bug depends on a long string, unusual character, duplicate value, null value, or specific date, create a safe sample with the same shape.

Step 6: Capture the environment and commands

A reader should be able to understand how the example was created and run. Include a short environment section, such as:

OS: Windows 11 24H2
Runtime: Node.js 22.10.0
Package manager: npm 10.9.0
Framework: Example Framework 4.2.1

Install:
npm install

Run:
npm test

If dependency versions matter, include a lockfile or list exact versions. Avoid saying “latest,” because versions change and can eliminate or introduce the bug. If the issue only occurs with a range of versions, state the tested range and the version that reproduces it.

A compact issue summary can use this format:

ItemDetails
ExpectedThe request returns HTTP 201 with a created record
ActualThe request returns HTTP 500 with TypeError: ...
ReproductionSubmit the included payload once
EnvironmentNode.js 22.10.0, Windows 11, package 4.2.1
FrequencyHappens every time in the supplied example

The table is not a replacement for the actual code and commands, but it gives readers a quick orientation.

Step 7: Verify the example on a clean setup

A reproduction is stronger when you test it outside your original development environment. Create a new directory, virtual environment, container, or temporary machine if practical. Follow your own instructions from the beginning.

During this check, look for hidden assumptions:

  • A package installed globally but missing from the project
  • A file referenced by an absolute path on your computer
  • An environment variable that was not documented
  • A database schema that already existed locally
  • A browser extension or editor plugin affecting behavior
  • A cached build artifact
  • A different locale or time zone

If the example only works after several undocumented manual actions, it is not yet self-contained. Move those actions into a setup script, include the missing file, or explain the required configuration explicitly.

Test the expected behavior as well as the failure. If you claim that one input succeeds and another fails, verify both paths. This helps identify whether the issue is caused by a particular value or by the entire operation.

Step 8: Share the smallest useful package

Choose a format that matches the problem:

  • A code block is best for a short script or configuration.
  • A repository is useful when several files are required.
  • A gist or archive can work for a small multi-file example.
  • A container configuration helps when system dependencies matter.
  • A test case is ideal for a library or framework bug.
  • A network trace may be needed for protocol or HTTP problems.

Include a README with setup, reproduction, expected output, actual output, and version information. Name files clearly. A person should not need to inspect the entire project to find the command that demonstrates the problem.

If the platform has length limits, provide a public reproduction link and summarize the critical files in the post. If the code cannot be shared publicly, ask whether a private channel is available and explain which parts cannot be disclosed.

Common mistakes and how to fix them

The example is still too large. Remove features until the failure disappears, then restore only the last removed piece. Repeat this process.

The example does not reproduce the bug. Compare versions, input data, operating system, configuration, and execution order. Ask another person to follow the instructions exactly.

The report contains only a stack trace. Add the smallest input and command that produces it. A stack trace shows where the program stopped, not necessarily what caused it.

The report says “it doesn’t work.” State the expected and actual results, including status codes, values, visual symptoms, or timing.

The example depends on a private service. Replace it with a fixture or mock unless the service is the subject of the bug.

Too much code was changed during cleanup. Restore the original behavior from your copy and simplify one change at a time. A large rewrite can create a new bug or conceal the original one.

The issue is intermittent. Record frequency, timing, concurrency, and any random seed if available. Include logs from both successful and failed runs, after removing sensitive data.

The problem might be a limitation rather than a defect. Check the relevant documentation and test a supported configuration. If the behavior is documented, describe the gap between the documented behavior and your intended use instead of labeling it a bug.

A reusable bug report template

You can adapt this structure for an issue tracker, support request, or forum post:

## Summary
One sentence describing the observable problem.

## Environment
- OS:
- Runtime:
- Package/framework version:
- Relevant configuration:

## Steps to reproduce
1. Create the project with ...
2. Run ...
3. Provide this input: ...

## Expected result
Describe the correct behavior.

## Actual result
Describe what happens, including the exact error or output.

## Minimal example
Include a link or the complete code needed to run it.

## Additional notes
Mention workarounds, frequency, and results from other versions.

Before publishing, follow the instructions from a clean directory, confirm that the example still fails for the documented reason, and check every attachment for secrets. A well-reduced reproduction does more than make a bug report look organized: it turns an uncertain investigation into a small, testable problem that someone else can solve.

Written by

shiftedup.com Editorial Team

Editorial team

Independent editorial coverage of code & developer life.