Reproducing a Bug From a Sentry Issue

Written By  Crosscheck Team

Content Team

May 24, 2026 9 minutes

Reproducing a Bug From a Sentry Issue

Reproducing a bug from a Sentry issue

An alert lands in your team channel: TypeError: Cannot read properties of undefined (reading 'currency'), 412 events, 88 users affected. You open the issue, look at the stack trace, run the same page locally, and everything works.

The issue is not lying. You are just missing four or five details that the 88 users had and you do not. Sentry recorded most of them. The job is to read the event carefully enough to rebuild the conditions.

Short version

  • Read the event, not just the title. The title is a grouped label; the event has the evidence.
  • Tags tell you who and where: release, browser, URL, environment, user.
  • Breadcrumbs tell you what happened before: clicks, navigation, network requests, console output.
  • The release tag lets you check out the exact code that crashed, which removes most false starts.
  • Reproduce on the same release first. Only then move forward to main.
  • If three honest attempts fail, write down what you tried and add the instrumentation you wish you had.

An issue is not one bug

Sentry groups similar events into an issue using a fingerprint, usually built from the error type and the top stack frames. That grouping is helpful and occasionally wrong.

Before you spend an hour on a repro, check whether the issue is really one problem:

  • Open the All Events list and look at three or four events from different users.
  • Compare their tags. If some are on release 2.9.0 and others on 3.1.0, or some on Safari and some on Chrome, you may have two different causes wearing the same label.
  • Look at the event graph. A flat line that starts on a specific day points at a deploy. A steady trickle points at an edge case in the data.

Pick one representative event and work from that. Trying to reproduce "the issue" in general is how people end up chasing three bugs at once.


Step 1: read the tags

Tags are the searchable key-value pairs attached to every event. They answer "under what conditions did this happen?"

The ones that matter most:

TagWhy it matters
releaseThe exact build. Lets you check out the same code.
environmentProduction, staging, or preview. A staging-only error often means bad test data.
urlThe page. Look at the path parameters, not just the route.
browser / browser.nameVersion-specific bugs are common, especially in Safari.
osRarer, but decisive for file, clipboard, and date bugs.
userThe account. Role and plan usually explain "works for me".
transactionThe route or component the error belongs to.
Custom tagsFeature flags, tenant ID, plan tier — whatever your team adds.

The habit that pays off most is the tag distribution panel. Sentry shows the percentage split for each tag across the issue. If browser.name: Safari is 100%, you have your first real clue and can stop reading. If plan: free is 96%, the bug lives in a code path that paying accounts skip.

If your app does not set custom tags yet, this is the moment to add them. A tenant, plan, and flags tag turns future triage from an hour into two minutes.


Step 2: read the breadcrumbs backwards

Breadcrumbs are the timeline of what happened in the session before the error. Sentry records them automatically: navigation, clicks, network requests, console messages, and anything you add yourself.

A real breadcrumb trail looks like this:

14:32:01  navigation   /projects  ->  /projects/882/invoices
14:32:03  ui.click     button#export-invoices
14:32:03  fetch        GET /api/v2/invoices?project=882   200   412ms
14:32:04  console      warn  "pricing block missing for legacy plan"
14:32:04  ui.click     button.currency-toggle
14:32:04  error        TypeError: Cannot read properties of undefined

Read it from the bottom up. Six lines tell you nearly everything:

  1. The error follows a click on the currency toggle.
  2. One second earlier the app warned that a pricing block was missing.
  3. The invoice request succeeded, so this is not a network failure.
  4. The user came from the projects list, so state may have been carried over.

Now you have a hypothesis you can test: the currency toggle assumes a pricing block that legacy plans do not have.

Three things to look for every time:

  • The last network request before the error. Its URL, status, and duration. A 200 that returns an unexpected shape causes more bugs than a 500.
  • The last user action. Clicks and input changes are recorded with a CSS selector, which points you at the component.
  • Warnings you have been ignoring. Console breadcrumbs often contain the explanation your team wrote months ago and stopped reading.

One limit worth knowing: breadcrumbs are capped, usually at 100 entries. A long session drops the early ones. If the trail starts mid-flow, that is why.


Step 3: match the release

This step removes more wasted time than any other.

The release tag names the build the user was on. If it says a1b2c3d and you are testing against today's main, you may be testing code that already changed. Check out the same commit:

git checkout a1b2c3d
npm ci
npm run dev

Two extra checks:

  • Compare against the current release. Sentry shows whether the issue is still occurring on newer releases. If the last event was on 2.9.0 and you are on 3.1.0, it may already be fixed.
  • Look at the "first seen" release. If the issue first appeared in 2.8.4, the cause is in the diff between 2.8.3 and 2.8.4. That is often a small enough range to read.

If the trace is unreadable — full of names like t.n (main.4f2a.js:1:88213) — your source maps are not being uploaded for that release. Fix that before anything else. Guessing at minified frames is not debugging.


Step 4: rebuild the conditions

Now turn the evidence into steps. Work through these in order and stop as soon as it fails.

  1. Check out the release commit and run the app locally.
  2. Recreate the account state. Match the role, plan, and workspace from the user tag. Create a test account such as [email protected] with the same plan tier rather than using a real customer's login.
  3. Recreate the data. This is the step people skip. If the breadcrumb showed /api/v2/invoices?project=882, look at what project 882 actually contains — a legacy plan, an unusual currency, 600 line items, a name with an apostrophe.
  4. Match the browser. If the tag distribution points at one browser and version, use it.
  5. Set the same feature flags. From your custom tags or your flag provider's dashboard.
  6. Follow the breadcrumbs as literally as you can. Same entry page, same clicks, same order. Order matters more than people expect, because it determines what state is already in memory.
  7. Watch the console and network as you go. You are looking for the same warning and the same response shape, not only the same crash.

If it still passes, one shortcut often works: skip the UI and call the failing code directly with the data from the event. If the error object includes the response body or the component props, feed those values into the function from the top stack frame. A failing unit test written from real production data is a better repro than a manual click path, and it stays as a regression test.


When you cannot reproduce it

Three honest attempts is a fair limit. After that, change the goal from "reproduce it" to "make the next event tell me more."

  • Add context at the failure point. Attach the values you wish you had: Sentry.setContext('invoice', { planTier, currency, lineItemCount }). The next event answers the question for you.
  • Add breadcrumbs by hand around the suspicious flow, so the timeline shows internal state and not just clicks.
  • Add a tag for the condition you suspect, such as has_pricing_block: false. Then check the tag distribution after a day.
  • Check session replay if your team has it enabled. Watching the session usually settles it in a minute.
  • Ask the user. For a small number of affected accounts, a support message with two specific questions beats a week of guessing.

Sentry events are also one-directional: they tell you what the machine saw, not what the person expected. When the gap between those two matters, a human-filed report helps, and tools such as Crosscheck capture the screenshot, console log, network requests, and environment details from the page so the report arrives with the same evidence an automatic event would have.


What to write in the ticket

Once you have a repro, record it so nobody has to redo the work:

Repro (confirmed on release a1b2c3d, Chrome 141, staging)
Account: [email protected] (plan: Legacy, role: Editor)
Data: Project 882, invoice in EUR, no pricing block on the plan

1. Sign in and open https://staging.example.com/projects/882/invoices
2. Click "Export invoices" and wait for the list to load
3. Click the currency toggle

Expected: currency switches to USD
Actual: page goes blank, TypeError in console (Sentry issue FE-2291)

Link the ticket to the Sentry issue in both directions. When a fix ships, the issue can be marked as resolved in the next release, and Sentry will reopen it automatically if it comes back — which is the cheapest regression test you will ever get.


Frequently asked questions

Why can I never reproduce production errors locally? Usually data and account state, not code. Production has old records, unusual currencies, large collections, and users with roles you do not test. Match those before you doubt the report.

What if the stack trace is all minified names? Source maps are not reaching your error tracker for that release. Fix the upload first; a minified trace is not worth reading.

How many events should I look at before deciding on a cause? At least three, from different users. One event can be a fluke. Three with the same tag pattern is a real signal.

Should I close an issue I cannot reproduce? Do not close it silently. Add the context or tags you need, note what you tried, and set it to review after a few days of new events.

Are breadcrumbs safe to read? They can contain personal data from URLs and form fields. Treat them like any other production data, and scrub sensitive fields in your SDK configuration.

Related Articles

Contact us
to find out how this model can streamline your business!

Trusted by thousands ofengineering teams worldwide.

Add to Chrome
200+ reviews · 100k+ users
Crosscheck browser extension capture controls

Join the Crosscheck Community

Stay in the loop with Crosscheck's newest features and insights.