The Defect LedgerSeverity · priority · triage

Defect board › Reproduction

Recording Steps for Bugs Only One Machine Can Trigger

Logged 2026-10-21

01 Overview

Some defects refuse to travel. They appear on one developer's laptop, one tester's virtual machine, one customer's older operating system build, and nowhere else. The report lands in the queue looking thin: a screenshot, a vague sentence, and a note that nobody else can make it happen. The instinct is to call it flaky, close it, and move on. That instinct is often wrong, and it is expensive.

A defect that only one machine can trigger is still a defect. The machine is not the bug, but it is part of the trigger, and the trigger is what you are trying to record. Your job as the reporter is not to prove the bug is universal. Your job is to describe the machine and the actions precisely enough that someone with the authority to provision that machine can reproduce the failure on purpose.

This article is about the craft of writing those reports. It covers what the report is actually claiming, how severity and priority diverge when the environment is narrow, how to write steps that survive a handoff, how to run the triage conversation, and what to do when the defect comes back after being closed. The through-line is simple: environment is data, and data belongs in the report.

02 What the report is actually claiming

When you file a bug that only reproduces on your machine, you are making a compound claim. The first part is that a failure occurred. The second part is that the failure depends on something about the environment you ran it in. Those are different claims, and conflating them is the most common mistake in these reports. If you write only the first part, reviewers will assume the second part is false, and they will treat the bug as unreproducible noise.

State the environment dependency as a hypothesis, not an excuse. Instead of writing that it only happens on my machine, write what you observed: the failure occurs on this OS build with this runtime version and this locale, and does not occur on the baseline configuration you also tested. That sentence does real work. It tells the reader that you ran a control, that you have a comparison, and that the difference between the two runs is a lead rather than a mystery.

Be honest about what you have not tested. If you only tried one other machine, say so. If you have not checked whether the failure depends on the OS, the hardware, the installed extensions, or the network path, list those as open questions. A report that names its own uncertainty is far more useful than one that asserts a cause it cannot support. Reviewers can act on open questions. They cannot act on a confident guess.

03 Severity versus priority

Severity describes how much damage the defect causes when it fires. Priority describes when the team intends to fix it. These are independent axes, and a one-machine bug is where the difference becomes vivid. If the failure corrupts data, blocks a release workflow, or produces a wrong result that a user might trust, severity is high regardless of how few machines can reach it. The narrowness of the trigger does not reduce the damage; it reduces the population exposed to the damage.

Priority is where the environment enters the calculation. A high-severity defect that only appears on an unsupported configuration may sit at medium priority for a long time, because the team has decided that configuration is out of scope. That is a legitimate decision, but it should be made explicitly and recorded, not smuggled in by quietly downgrading severity. When someone later asks why a data-corrupting bug was never fixed, the answer needs to be a documented scope call, not a shrug.

Watch for the reverse error as well. Teams sometimes inflate priority because a bug is embarrassing or because a senior person hit it, even when the damage is cosmetic. That distorts the queue and trains people to ignore priority labels. The discipline is to score severity from the failure and priority from the plan, then let the triage meeting reconcile the two. If they disagree, that disagreement is the useful signal, and it belongs in the record.

04 Writing steps someone else can follow

Start with the environment fingerprint, before the steps. List the operating system and build number, the architecture, the locale and language settings, the runtime or framework versions, the relevant driver or firmware versions, and any extensions, plugins, or third-party tools that are loaded. If the machine is a virtual machine or a container, say so and describe the host. This block is boring to write and invaluable to read, because it is the only part of the report that lets someone else decide whether their machine is even a candidate.

Then write the shortest ordered sequence that reaches the failure from a clean starting state. Number the actions. Use one action per line and name the exact control or command you used. Avoid summarizing a five-minute exploration as one sentence; the exploration is not the reproduction. If you had to restart a service, clear a cache, or toggle a setting before the failure appeared, that belongs in the sequence, because it may be the trigger. End with the observed result and the expected result, stated separately and concretely.

Finally, include the control run. Describe the machine where the same steps did not fail, and note the differences between the two environments. This is what separates a credible environment-specific report from a complaint. The control run does not need to be exhaustive; one known-good comparison is enough to establish that the steps are not simply broken for everyone. If you cannot run a control, say that too, and mark the environment dependency as unverified.

05 Running the triage queue

Triage for these reports is a routing decision, not a verdict on whether the bug is real. The first question is ownership: which component team owns the surface where the failure appears? The second question is environment ownership: who can provision or emulate the machine that triggers it? Those are often different people, and the report should be routed to both. A bug assigned only to the component team will stall, because that team may not have the hardware or the image to reproduce it.

The triage meeting should force one of four explicit outcomes. Fix it now, with an environment owner attached. Fix it later, with a documented reason and a trigger to revisit. Work around it, with the workaround written down for affected users. Or document the limitation, with the scope decision recorded where support and future maintainers can find it. What triage must not do is leave the report open and unowned, because that is how environment-specific bugs rot in the backlog for years.

Keep the environment fingerprint attached through every state change. When the report moves from open to confirmed, the fingerprint moves with it. When it moves to fix-in-progress, the engineer needs the fingerprint to build a test. When it is closed, the fingerprint is the evidence that the closure was justified. Treat that block of text as a first-class artifact, not as preamble that can be trimmed for tidiness.

06 When a defect comes back

A closed environment-specific bug that reappears is not a failure of the original report. It is new information. The first thing to check is whether the environment changed: a new OS build, a driver update, a new extension, a different locale, a hardware replacement. If the fingerprint shifted, the defect may be the same underlying flaw reaching a new trigger, or a genuinely different failure that happens to look similar. Compare the old fingerprint to the new one before assuming anything.

If the environment is unchanged and the bug still fires, the original closure was premature. Reopen with the new evidence rather than filing a duplicate, so the history stays in one place. Add the date, the exact configuration, and what you did differently this time. If the bug now reproduces on additional machines, say so prominently, because that changes the priority calculation and may move the defect out of the environment-blocked category entirely.

If the bug cannot be reproduced again even on the original machine, do not force a conclusion. Record the attempt, the configuration, and the outcome, and leave the report in a state that reflects uncertainty. Intermittent and environment-bound failures are genuinely hard, and a report that documents a failed reproduction attempt is still valuable. The next person who sees the symptom will start from your notes instead of from zero.

07 Frequently asked questions

Is a bug that only one machine can trigger worth filing at all? Yes, if you can describe the machine and the steps. The value of the report is not that it proves a universal defect; it is that it preserves a reproducible observation and the environment that produced it. A well-written report lets someone else decide whether that environment matters to the product.

Should I downgrade severity because the trigger is narrow? No. Severity follows the damage, not the population. Narrow the priority if the configuration is out of scope, and record that scope decision explicitly. Mixing the two axes is what makes these reports confusing to review.

What if I cannot run a control on another machine? Say so in the report and mark the environment dependency as unverified. Reviewers can still route the bug and assign an environment owner. An honest gap is easier to work with than a fabricated comparison.

How long should the environment fingerprint be? Long enough that a reader can tell whether their machine is a candidate. Include the dimensions you actually varied or suspect: OS build, architecture, locale, runtime versions, drivers, extensions. Omit dimensions you know are irrelevant, but note that you checked them.