Blog

Error grouping and fingerprinting, explained

3 min read

Grouping is the invisible feature of an error tracker: when it works you never think about it, and when it fails you drown in duplicate issues or — worse — miss a real bug hiding inside an unrelated one. Here's how Sentry-style fingerprinting actually decides that two events are 'the same', and how to take control when the defaults get it wrong.

The problem: same bug, different-looking events

Two occurrences of the same bug rarely produce byte-identical events. Line numbers shift between releases. Async boundaries reshuffle stack frames. Messages embed user ids, timestamps and URLs. A naive equality check would open a new issue for nearly every event; grouping exists to see through the noise.

How exception fingerprinting works

For events with a stack trace, the fingerprint is built from the exception type plus a normalized signature of the in-app frames:

  • Frames from libraries and the runtime are dropped when in-app frames exist — your code is the stable part.
  • Filenames are reduced to their basename and function names are stripped of namespaces (Object.handlerhandler).
  • Absolute line/column numbers are ignored — they churn with every deploy.
  • Consecutive identical frames collapse, so a recursive crash at depth 3 groups with the same crash at depth 3,000.
  • Chained exceptions (caused by) are folded in, so a wrapper error with a different root cause becomes a different issue.

Message events: parameterization

Events without a stack trace group by their message — after the volatile tokens are replaced with placeholders. Payment failed for order #48213 (took 3.2s) becomes Payment failed for order #<int> (took <float>s), so every occurrence lands in one issue. Good parameterizers handle ints, floats, UUIDs, hashes, emails, URLs, IPs and dates.

This is why logging raw IDs into error messages is fine for grouping — but logging entire JSON payloads is not. A different payload shape per event can defeat parameterization and shatter one bug into hundreds of issues.

When defaults fail: custom fingerprints

Two classic failure modes: over-grouping (a generic TimeoutError from your HTTP client groups together for every downstream API) and over-splitting (a minified frontend without source maps produces different mangled frames per build). Both are fixed with explicit fingerprints in the SDK:

Sentry.captureException(err, {
  fingerprint: ['api-timeout', targetService],
});

Server-side grouping rules

SDK fingerprints require a deploy. Server-side rules don't: a pattern like type:TimeoutError message:*payments* → fingerprint payments-timeout regroups matching events from the moment you save it. jentry supports both, mirroring Sentry's semantics, so your existing mental model (and your existing custom fingerprints) carry over unchanged.

Practical grouping hygiene

  1. 1Upload source maps (or ship server-side symbols) — grouping quality on minified code is grouping quality on garbage otherwise.
  2. 2Keep exception messages human-readable and put variable data in tags/extra, not in the message.
  3. 3Review your top 10 issues monthly: if one issue is clearly two bugs, split it with a fingerprint rule.
  4. 4Treat 'ignore' as a grouping tool — an issue you'll never fix should stop generating noise.

Frequently asked questions

Why did one bug create hundreds of issues?

Usually missing source maps (each release produces different minified frames) or dynamic data defeating message parameterization. Fix the maps first; add a custom fingerprint if the events still split.

Why did two different bugs group into one issue?

They likely share their in-app stack signature — common with generic wrappers (HTTP clients, ORMs). Add a custom fingerprint that includes the distinguishing dimension, like the downstream service name.

Do custom fingerprints from Sentry SDKs work with jentry?

Yes. jentry reads the same fingerprint field the Sentry SDKs send and applies the same override semantics, so existing code keeps working when you point the DSN at jentry.

Does changing grouping rules re-group old events?

Like in Sentry, rules apply to events from the moment they exist — history stays where it was. Plan grouping changes when a noisy issue is active, not after it quiets down.

Try jentry free

Hosted error tracking & performance monitoring. Works with your Sentry SDKs — send your first event in minutes.

How Error Grouping & Fingerprinting Works (Sentry-style) | jentry