Bug reproduction when only one customer account is affected

A bug reproduction method for issues that hit one customer account: account-specific causes, the order to gather evidence, a worksheet and a clean handoff.

When a bug affects only one customer account, the cause is almost always something that’s different about that account: its data, configuration, flags, plan, integrations or the customer’s environment. Bug reproduction then becomes a comparison. Find what differs from an account that works, show which difference matters, and rebuild it in a test account engineering can use.

The usual dead end is trying the steps in your own account, seeing everything work, and replying “can’t reproduce”. Your account is the control, not the test. This guide covers where account-specific bugs come from, the order to gather evidence, a worksheet, and what a good handoff contains.

If the symptom is a missing button or a 403, start with debugging customer permission issues instead. That guide covers roles, grants and entitlement checks in depth. This one covers everything else.

Why does a bug affect only one customer account?

Because the code path is shared but its inputs aren’t. Every account feeds the same code different data and settings, and one combination hits a case nobody tested. These are the usual suspects:

CauseWhat’s different about the accountWhere to look
Data shapeA null field, a legacy record, unusual characters, a duplicateThe specific records the failing page or job reads
Data volume40,000 items where most accounts have 400Row counts, payload sizes, pagination and timeout logs
Feature flagsA rule targets this user, tenant, locale or cohortFlag evaluation logs and the context the flag was evaluated with
Plan or entitlementA legacy plan, add-on, trial or grace periodBilling record compared with the app’s derived entitlements
Tenant configurationCustom fields, workflow rules, SSO or region settingsSettings diffed against a working tenant
Locale and timezoneDate boundaries, number formats, right-to-left textUser and tenant locale settings, server versus browser time
IntegrationsAn expired third-party token, a stuck sync, a webhook failingIntegration status, the last successful sync, error logs
Customer environmentBrowser version, extensions, corporate proxy, blocked scriptsBrowser console and network errors from the customer’s machine

Feature flags deserve extra care. A flag’s result can depend on who is asking and when. The OpenFeature specification (opens in a new tab) describes flag evaluation context as data about the user, the application or the host, such as an email address, locale or time of day. Your admin account and the customer’s account can get different answers from the same flag.

What evidence should you collect first?

Collect the cheapest, least invasive evidence first and stop as soon as one source explains the bug. A good order:

  1. The exact report. Who, which account, which action, when (with timezone), what they expected and what happened. Ask for a screenshot of the error, not a description of it.
  2. Logs and request IDs. Find the failing request by account and timestamp. A request ID links every event from one interaction. OWASP’s Logging Cheat Sheet (opens in a new tab) calls this an “interaction identifier” and recommends recording it so related events don’t need to be reconstructed later. A stack trace with an account ID often ends the investigation here.
  3. A configuration diff. Compare the affected account with a working account on the same plan and region. More on this below.
  4. Replay and browser diagnostics, if you have them. A recording of the session can show what happened on screen. It can’t show server-side state, so read when session replay isn’t enough before relying on it alone.
  5. A synthetic reproduction. Build a test account that copies the differences you found.
  6. Approved access to the current account. Only when the earlier steps leave a gap that only the live account can fill.

Each step is a cheaper experiment than the next, and each one narrows the search. Skipping straight to step 6 is tempting. It’s also the step most likely to change things, expose unrelated customer data, or show you a state that no longer matches the report.

How do you compare the account with one that works?

Pick a control account that should behave the same: same plan, same region, similar size, ideally one that uses the same feature successfully. Then diff the inputs, not the screens.

Export both accounts’ settings, flag evaluations for the relevant flags, entitlements and integration states as structured data, and compare them side by side. Add counts and shapes for the records involved: how many items, the oldest record’s date, and fields that are null in one account and not the other.

Here’s a fictional example. Customer Larch reports that their invoices page shows a blank screen. Your control account loads it fine. The logs show a TypeError while rendering one invoice. The diff shows Larch has one invoice, imported years ago, with no due date, while every invoice in the control account has one. That’s a data-shape hypothesis you can test without opening Larch’s account at all.

Keep the diff out of the ticket if it contains customer data. Store it where access is controlled, and put the request IDs and field names in the ticket instead.

How do you reproduce the bug without the customer’s account?

Rebuild the difference in a test account, using synthetic data that copies the shape but not the content. In the Larch example, create a test tenant with one invoice whose due date is null and load the page. If it fails the same way, you have a reproduction that engineering can run as often as they like.

Change one input at a time. If you copy a large dataset and three settings at once and the bug appears, you still don’t know which input caused it. Mozilla’s bug-writing guidelines (opens in a new tab) call precise steps to reproduce “the most important part of any bug report”. The same guidelines ask reporters to say whether a bug reproduces in a new browser profile and, if not, which settings or extensions it needs. Ask customers the same thing: have them try a private window or a clean profile with extensions turned off before you go looking for account causes.

Then prove the cause works in both directions. These are pass conditions to check, not results we’ve run.

CheckPass condition
Test account with the suspected differenceFails the same way as the customer’s account
Same test account without the differenceWorks
Control account after you add the differenceStarts failing
Fix applied in staging, difference still presentWorks, and the original error is gone from logs
Other accounts with the same differenceFound by a query, so you know the true blast radius

The last check matters. “Only one customer” often means “only one customer who reported it”.

When should you look at the customer’s live account?

When the evidence points at something you can’t copy: a record you aren’t allowed to export, an integration’s live state, or a configuration combination you can’t reconstruct. At that point a short, approved look at the account is the right tool. Without one, you’re guessing.

Keep it narrow. Write down the one question the session must answer, use read-only access where possible, and end it when you have the answer. Don’t change the customer’s role or settings to “see if it helps”, because that destroys the state you’re investigating. Remember that what you see is the account as it is now. It won’t recreate last week’s flag rollout or the customer’s laptop.

Devora handles this step. A team member picks the customer and requests a scope, duration and reason (opens in a new tab). An approver or admin in your organization reviews the request, and Devora keeps the requests, approvals and session records for audit. Read-only scope is enforced by a backend guard on your API routes (opens in a new tab), not only in the UI. Recording is optional (opens in a new tab) and off by default. Devora doesn’t find root causes for you. It controls the access step at the end of the investigation.

Use a worksheet for each investigation

One worksheet per ticket keeps the investigation honest. Leave a field blank rather than filling it with a guess.

FieldWhat to enter
ReportAccount, user, action, time with timezone, expected and actual result
Request evidenceRequest IDs, status codes, error messages, log links
Control accountWhich account and why it’s comparable
Differences foundData shape and volume, flags, plan, configuration, integrations, locale, environment
HypothesisThe one difference you think causes the bug
Synthetic reproductionTest account or fixture, steps, result
Live-account accessNot needed, or the approved question, scope and outcome
Blast radiusOther accounts with the same difference
StatusConfirmed, hypothesis, or not tested

What should a bug reproduction handoff include?

A reproducible case, not a story. Engineering should be able to run your steps against your fixture and see the failure without contacting the customer.

Include the completed worksheet, the exact steps, the test account or fixture, and the expected versus actual result. Name the difference from the control account and the evidence for it. Say plainly what’s confirmed, what’s a hypothesis and what you didn’t test. Link logs by request ID instead of pasting customer records, tokens or screenshots full of personal data.

If the worksheet still has a gap that only the live account can fill, that’s when controlled access earns its place. To see how an approved, read-only session fits your stack, create a Devora account and try one staging session.

Sources

Quick answers

Common questions, answered clearly.

Direct answers to the questions teams usually ask when evaluating this approach.

Why can't I reproduce a bug that one customer reports?

Your test account is probably missing whatever makes theirs different: an unusual record, a flag result, a legacy plan, a tenant setting, an integration's state or their browser setup. Compare the affected account with a similar one that works, then copy the differences into a test account one at a time.

What should I check first when only one customer has a bug?

Start with the failing request: its timestamp, request ID, status and error in your backend logs. That often names the cause directly. Next, diff the account's configuration against a working account on the same plan before you touch the customer's account.

Should I log in as the customer to reproduce the bug?

Only after logs, a configuration diff and a synthetic reproduction have run out, and only with approved, time-limited, preferably read-only access. Logging in shows how the account behaves now. It doesn't recreate the customer's device, network or the account's earlier state.

How do I write a reproducible bug report for engineering?

Give exact steps, expected and actual results, the account inputs that differ from a working account, and a fixture or test account that shows the failure. Mark each finding as confirmed, a hypothesis or not tested, and link evidence by request ID rather than pasting customer data.

What if the bug only happens on the customer's computer?

Then the cause is likely in the environment rather than the account: browser version, extensions, a corporate proxy, locale or timezone settings. Ask the customer to try a private window or a fresh browser profile with extensions off, and capture the browser console and network errors.

Put it into practice

Give your team context.Keep control of access.

Bring approvals, scoped sessions, and access history into your support workflow.