BugMojoBugMojoBugMojo
FeaturesPricingBlogHelpAbout
Add to ChromeLog inGet started
BugMojoBugMojo

Bug reports that actually help fix bugs — capture, replay, share.

A product of Softech Infra.

Product

  • Features
  • Pricing
  • Browser extension
  • Get started
  • Log in

Resources

  • Help & guides
  • Blog
  • Compare
  • Glossary

Company

  • About
  • Contact
  • Security
  • Privacy
  • Terms
  • Sitemap
© 2026 BugMojo. All rights reserved.
AllGuidesEngineeringPlaybooksCompareGlossaryAlternativesBy roleBug tracking by framework
  1. Home
  2. Blog
  3. Glossary
  4. What Are Reproduction Steps? How to Write Steps That Actually Repro
Glossary

What Are Reproduction Steps? How to Write Steps That Actually Repro

Reproduction steps are the ordered actions that reliably trigger a bug from a known starting state. Here is the anatomy of steps that actually repro, and why steps alone still fail on some bugs.

ManviManvi·Jun 5, 2026·9 min read
Glossary
A horizontal rail of five numbered step-nodes threaded by a lime tracer line, the last node cracking into a failure burst that continues into a console, network, and replay state cluster read by an AI agent glyph
TL;DR
  • Reproduction steps (STR) are the ordered, numbered actions that reliably trigger a bug from a known starting state.
  • A complete set carries five parts: preconditions, numbered atomic actions, test data, expected vs actual, and environment — the shape GitHub and Atlassian both enforce in their bug forms.
  • Steps capture actions, not state: about 17% of bugs are non-reproducible and stay open ~3 months longer.
  • For intermittent bugs, record the frequency and attach a replay of one real failure — a description of a flaky bug is not a reproduction.

Definition

Reproduction steps are the ordered, numbered actions that reliably trigger a bug, written from a known starting state so anyone can recreate the failure. They are paired with the expected result and the actual result observed at the point things break.

You will also see them as repro steps, steps to reproduce, or the acronym STR. The core is always the same triad: a numbered path of actions, what you expected to happen, and what actually happened. GitHub bakes exactly these three fields into its issue-form templates — 'Steps to reproduce', 'Expected behavior', 'Actual behavior' — making the structure the de facto standard enforced at file time across millions of repositories. Atlassian's bug-report template uses the same spine and adds the operational fields — environment, severity, and evidence — that turn a description into something a team can act on. This page defines STR, breaks down its anatomy, and is honest about where steps stop working; for the full six-field report it lives inside, see the bug report template guide.

The anatomy of steps that actually repro

Most reports fail not because the writer left something out, but because they described only the clicks. A reproduction that survives handoff to a stranger has five distinct parts, and each one closes a specific gap where reproducibility leaks away.

1. Preconditions (the entry state.) Where does the reader start? 'Logged out, on /checkout, cart empty' removes the guesswork about setup. Software Testing Help is explicit that you should start from a clean, known state and never assume or skip a reproducing step — the person following your report should be able to complete each line without inventing context. 2. Numbered atomic actions. One action per line, in order, with no 'and then' chains that hide a branch. Atlassian calls the numbered, explicit list of actions the single most vital section of the report. 3. Test data. Name the exact values: 'enter -1 in the Quantity field', not 'add some items'. The triggering value is frequently the whole bug. 4. Expected vs actual, stated at the failing step, because ambiguous expectations are not cosmetic: the data-fusion study of 576 non-reproducible reports found ambiguous or outdated expected behavior drove about 8% of non-reproducibility on its own. 5. Environment. OS, browser, build, and account. A step that fails on Chrome and passes on Safari is only reproducible once the reader knows which one you were on — which is why Atlassian treats environment, severity, and frequency as first-class fields rather than optional notes.

The shape of a step that repros
  1. Entry state: where the reader starts — 'Logged out, on /checkout, cart empty.'
  2. Numbered actions: one action per line, naming the exact element and value — no 'and then' chains.
  3. Expected vs actual: stated at the failing step — 'Expected: validation error. Actual: 500, blank page.'

A bad report, rewritten

The gap between a report that bounces and one that gets fixed is almost always concreteness. Here is the same bug written twice. The first version is what triage teams see most often; the second is what Mozilla, Atlassian, and every QA authority are actually asking for.

repro-steps.txttext
# BAD — a description, not a reproduction
Title: Checkout is broken
Steps: I tried to buy something and it didn't work.
       Add some items and check out, you'll see the error.

# GOOD — a recipe anyone can re-run
Title: Checkout returns 500 when cart quantity is set to a negative number

Preconditions: Logged in as a standard user, on /checkout, one item in cart.
Environment:   Chrome 138, macOS 15.4, staging (app.example.com), build 2.4.1.
Frequency:     5/5 attempts (always).

Steps:
  1. In the cart, click the Quantity field for "Blue Mug".
  2. Type -1 and press Tab.
  3. Click "Place order".

Expected: Inline validation error — "Quantity must be at least 1".
Actual:   Page goes blank. POST /api/orders returns 500.
          Console logs "TypeError: total is NaN".

The bad version is not lazy so much as under-specified: it names no entry state, no value, no environment, and no expected result, so the developer has to reconstruct all four before they can even start. The good version is not longer for the sake of it — every added line kills a specific question a triager would otherwise have to ask. Note the discipline Mozilla's Bug Writing Guidelines preach: minimize to the shortest sequence that still triggers the bug. Three atomic steps beat a paragraph. The -1 is the test data that is the actual trigger; the 500 and the NaN in the console are the actual result made unambiguous.

A horizontal reproduction recipe: five numbered step-nodes connected by a lime tracer line, the fifth cracking into a failure burst, then continuing into a state cluster of console, network, and replay icons that an AI-agent hexagon reads over a dotted MCP connector
A reproduction recipe: steps 1-5 are the actions; the failure burst is where expected and actual diverge; the state cluster (console, network, replay) is what turns the recipe from 'works for me' into a deterministic repro.

Why reproducibility drives fix time

Mozilla's guidelines are blunt about the stakes: 'Steps to reproduce are the most important part of any bug report. If a developer is able to reproduce the bug, the bug is very likely to be fixed.' The same page warns of the inverse — 'if the steps are unclear, it might not even be possible to know whether the bug has been fixed.' Reproduction is the gate. Triage priority, root-cause analysis, and the regression test that stops the bug coming back all depend on a developer being able to make the failure happen on demand.

The cost of missing that gate is measurable. The 'Works for me!' empirical study of Firefox and Eclipse quantified it: non-reproducible reports are about 17% of all bug reports and stay active roughly three months longer than reproducible ones. The reason those reports bounce is structural — steps capture actions, not state. The same five clicks can pass or fail depending on the API response, a feature flag, timing, cached data, the viewport, or the account. The data-fusion follow-up found roughly 14% of Eclipse's non-reproducible reports simply lacked the information required to reproduce. Tellingly, 66% of the non-reproducible reports that were eventually fixed had in fact been reproduced once enough information finally arrived — proof that the missing ingredient is almost always state, not effort.

Intermittent bugs and heisenbugs

The hardest reproductions are the ones that only fail sometimes — heisenbugs, in the folklore, because looking too closely makes them vanish. These are not rare edge cases; they are endemic even in mature, heavily automated systems. Google's Testing Blog reported that around 1.5% of all test runs are flaky and nearly 16% of their tests exhibit some level of flakiness — a test that both passes and fails against the same version of the code. The dominant causes are exactly the state variables that prose steps cannot capture: asynchronous timing and waits, concurrency and resource contention, and test-order dependence.

The reporting discipline for an intermittent bug is different in two concrete ways. First, record the frequency — '3 of 10 attempts', not just 'sometimes' — because a reader who does not know a bug is flaky will run your steps once, see it pass, and close the ticket as non-reproducible. This is why Atlassian's template makes frequency (always / occasionally / rarely) an explicit field. Second, stop trying to re-describe the failure and capture one. A session replay of a single real failure — with the console output and the network timing frozen at the moment it broke — is worth more than ten prose attempts to characterize a bug that only appears under conditions you cannot reliably re-create by hand. For a flaky bug, the replay is the reproduction.

FeatureTraitWeak repro stepsStrong repro steps
Entry state / preconditions—Unstated — reader guessesNamed: logged-out, /checkout, empty cart
Actions—Prose paragraph, 'and then' chainsNumbered, one atomic action per line
Test data—'add some items'Exact trigger value ( -1 in Quantity )
Expected vs actual—'it didn't work'Expected error vs actual 500 + console NaN
Environment——OS, browser, build, account
Frequency (for intermittent bugs)—'sometimes'5/5 (or 3/10) + a replay of one failure
Weak vs strong reproduction steps — the same bug, and why one gets fixed on the first read.

Caveats: when steps aren't enough

Perfect steps do not guarantee a reproduction, and pretending otherwise sends people chasing a wording problem that is really a state problem. Some bugs are environment-specific — they need a particular GPU driver, a corporate proxy, a specific browser build, or a locale, and no amount of clarity in the numbered list will surface them on a developer's clean laptop. Some are data-specific — they only fire for a row that already exists in one user's account, so 'reproduce with a fresh account' quietly hides the bug. Others are genuinely non-deterministic race conditions where the trigger is timing you cannot type into a step. In all three cases the steps are correct and the bug is still non-reproducible, which is exactly why the empirical data shows information — not effort — is the missing ingredient two-thirds of the time.

This is where capturing state alongside the steps stops being a nice-to-have. BugMojo's browser extension records the failure with the surrounding state attached — an rrweb session replay of exactly what the user did, the console output, and the network request that fed the data — so 'Step 3: click Place order, expected validation error, actual blank page' sits next to the precise POST /api/orders response and the NaN that produced the 500. For an environment- or data-specific bug, that bundle carries the account, build, and request the developer's clean machine does not have. State also matters once the reader is an agent: Cursor shipped a /debug command in April 2026 for bugs 'hard to reproduce or understand', where the agent forms hypotheses and uses runtime information to localize the fault — and an agent reading prose steps alone still guesses at the triggering state. Handing it the steps plus the replay, console, and network is the difference between 'reproduce this for me' as a hunt and the same request as a deterministic task.

Key takeaway

Reproduction steps capture actions; reproducing a bug needs state. Write the numbered path from a known entry state, with test data, expected vs actual, and environment — then, for anything intermittent, record the frequency and attach a replay of one real failure. Steps plus state is a reproduction, and a reproduction is what a developer (or an agent) can actually fix.

Ship the steps with the state that produced them
Install the extension

Frequently asked questions

Frequently asked questions

Sources

  1. Bug Writing Guidelines — Steps to reproduce are 'the most important part of any bug report' — Mozilla / Bugzilla (2025)
  2. Free Bug Report Template — steps to reproduce, expected vs actual, environment, severity — Atlassian (2026)
  3. How to Write a Good Bug Report — reproducibility, minimal steps, expected vs actual — Software Testing Help (2026)
  4. Flaky Tests at Google and How We Mitigate Them — ~1.5% of runs flaky, ~16% of tests — Google Testing Blog (2016-05)
  5. Works for me! Characterizing non-reproducible bug reports (Firefox + Eclipse empirical study) — Mozilla Foundation / Empirical Software Engineering (2022)
  6. Why are Some Bugs Non-Reproducible? An Empirical Investigation using Data Fusion — arXiv (ICSME 2020) (2021)
  7. Configuring issue templates — Steps to reproduce / Expected / Actual fields — GitHub Docs (2026)
  8. CLI Debug Mode and /btw Support — /debug for bugs 'hard to reproduce or understand' — Cursor / Anysphere (2026-04-14)
Share:
Manvi
Manvi· QA Tester

Manvi is a Quality Assurance Tester with three years of experience. For her, quality is not just about finding bugs — it is about ensuring the best possible experience for every user.

On this page

  • Definition
  • The anatomy of steps that actually repro
  • A bad report, rewritten
  • Why reproducibility drives fix time
  • Intermittent bugs and heisenbugs
  • Caveats: when steps aren't enough

Get bug-tracking insights, weekly.

Engineering deep-dives, QA playbooks, and honest tool comparisons. No spam — unsubscribe in one click.