Why Sentry Splits One Error Into Multiple Issues
Sentry splits one error into multiple issues because its grouping runs on a fingerprint computed from the event data, not on how similar two errors look to a person reading them. The fingerprint hierarchy checks a custom fingerprint first, then the stack trace, then the exception type and value, then the message, and it stops at the first one available. Two events that are obviously "the same bug" to you can land on different branches of that hierarchy, or the same branch with one differing detail, and Sentry has no step that asks whether they're really the same problem. It asks whether their fingerprints match. If they don't, two issues.
The gap is between what counts as identical to a person and what counts as identical to a hashing function. Sentry's own grouping documentation describes the fingerprint as built from stack trace frames when one exists, using module names, normalized filenames, and cleaned-up source context for the frames that belong to your application code. Change any of those inputs and the fingerprint changes with it, even though the underlying bug is unchanged.
The three usual causes
Minified or unsourcemapped JavaScript. Without accurate source maps, the frames Sentry sees are minified function and file names, a, b, chunk-4f2e1.js:1:8842, and those values differ between deploys even when the underlying code doesn't move. Two builds of the same bug produce two fingerprints. Sentry's grouping docs are direct about this one: minimized JavaScript source code "will destroy the grouping in detrimental ways," because the fingerprint is built from module names, normalized filenames, and cleaned-up source context per frame, and minified frames give it none of that to work with.
A wrapped or decorated call site. Middleware, error boundaries, retry wrappers, and instrumentation decorators all insert their own frames into the stack trace. If a bug fires from inside a retry wrapper on Tuesday and from a direct call on Wednesday because the retry logic changed, the top frames differ and so does the fingerprint, even though the exception being thrown is identical.
No stack trace at all. Some events, particularly from background jobs, webhooks, or SDKs configured without full tracing, arrive with an exception but no usable frames. Sentry falls back to exception-based grouping (type and value), which is coarser, or message-based grouping if even that's missing. A message that includes an interpolated value, an order ID, a timestamp, a user ID, defeats message grouping outright, because Sentry is hashing text that's different on every occurrence by design.
None of this is a Sentry bug. It's the tradeoff of grouping by content: content-based matching is precise when the content is stable and wrong when it isn't, and application code has a lot of ways to make stack traces unstable.
Fixing it going forward: fingerprint and stack trace rules
Sentry lets you override the default algorithm two ways, both configured per project under issue grouping settings:
- Fingerprint rules match on
error.type,error.value,stack.function, or similar fields and assign an explicit fingerprint, so you can tell Sentry that everyDatabaseUnavailableexception is one issue regardless of which frame it fired from, instead of letting the frame decide. - Stack trace rules do the narrower job of telling Sentry which frames to consider or ignore when it builds the hash, which is the direct fix for the wrapped-call-site problem above.
The catch that trips people up is that these rules are forward-only. They change how new events get fingerprinted; they do nothing to the issues that already exist. If a bug has been splitting for three months, writing a fingerprint rule today stops the fifth split from happening. It doesn't retroactively merge the first four.
Cleaning up issues that already split
For issues that already exist as separate entries, Sentry has a manual merge feature: select multiple issues from the issue list, or open one issue's Similar Issues tab, and merge them into a single issue with a combined event count. Two things about it are easy to miss:
- Merging only works for error issues, not performance or replay issues.
- Merging doesn't teach Sentry anything. The docs are explicit that merging issues doesn't infer a new grouping rule from the merge, so the next event with the same problematic fingerprint pattern still files as a new issue and you're back to merging manually.
Merging is cleanup for history, not a fix for the cause. The fingerprint or stack trace rule is what stops it from happening again.
Three low-priority pages that were actually one outage
Auric Health runs a scheduling platform for outpatient clinics, and its appointment-reminder service sits behind a retry wrapper the team shipped in August. A few weeks later the service started throwing an intermittent ReminderDispatchError, sometimes from inside a retry attempt, sometimes on the first try before retries kicked in. Each occurrence paged on-call at a low event count, and none of them alone crossed the alert threshold that would have flagged it as urgent.
Halvard Kessing, staff engineer, in
#eng-oncall: Getting paged forReminderDispatchErroragain, third time this week. Sentry's showing it as three separate issues, SENT-4471, SENT-4498, and SENT-4512, all low event counts. Is this actually one thing?
A teammate pulled up all three: same exception type and message, but the stack traces didn't match, two had the retry wrapper's frames on top and one didn't. That mismatch was the split. Confirming it was actually one root cause still took reading all three traces side by side, since Sentry's own view of them offered no shortcut.
It was one root cause. Halvard merged the three issues and wrote a stack trace rule so the wrapper's frames would stop mattering to the fingerprint going forward. The part worth noticing is the two weeks before that thread: three issues, each individually under the alert threshold, had been quietly tracking one outage the whole time. Appointment reminders were failing to send, intermittently, and nothing about the tooling made that visible until someone happened to ask whether three small things were actually one big thing.
The gap fingerprint rules don't close
Fingerprint and stack trace rules solve the Sentry-internal version of this problem, making sure the same bug produces one issue inside Sentry. They don't solve the adjacent problem, which is that the same bug can also show up outside Sentry, as a support ticket, a Slack message from an account exec, a line in a sales call, worded nothing like an exception message and carrying no fingerprint at all. In Halvard's case that gap never opened; the fix landed before any customer noticed. But it's a plausible next step for the same kind of bug: an intermittent ReminderDispatchError running for two weeks is exactly the sort of thing a clinic's ops lead might eventually notice and email support about, and nothing connects that email to SENT-4471 automatically, because Sentry only fingerprints what it receives as an event.
That's the layer Modem works on. Modem doesn't touch Sentry's grouping and isn't a replacement for fixing fingerprint rules; Modem's Sentry integration reads issues, stack traces, and sample events, and matches them against what customers are saying in Slack, support tickets, and calls, regardless of which Sentry issue ID a given occurrence filed under or whether the customer report ever mentions the exception at all. Modem is the company writing this guide. Judge the pitch on whether cross-system matching solves a problem you actually have, not on who's making it. The fingerprint and stack trace work in the sections above is worth doing regardless, since it's what stops Sentry from splitting the issue in the first place.
For the related question of matching an issue back to the accounts it hit, see how to find out which customers hit a Sentry error. The general version of "the same report keeps arriving under different names" is covered in our roundup of tools that deduplicate bug reports.
One check to run before the next page
Pick one recurring error you already suspect is splitting, open its Similar Issues tab, and check. If it's splitting on stack trace frames from a wrapper or minified build, merge the existing issues and write one stack trace or fingerprint rule so the next occurrence files where it belongs. That single rule usually accounts for most of a team's split-issue noise; the rest tends to be one or two other wrapped call sites you can find the same way.
