Why Sentry Ownership Rules Misroute Issues
An ownership rule that isn't routing issues correctly is almost never a broken rule. It's one of three specific Sentry behaviors that look like a bug from the outside: Sentry applies the last rule that matches an issue's stack frames, not the most specific one or the first one written; it only checks frames Sentry has marked in-app, so a match sitting in a vendored or third-party frame is invisible to it; and once an issue has been assigned at all, by a rule or by a person, Sentry turns off future auto-assignment for that one issue, permanently, even after new events arrive.
To find out which of those three is happening, check them in this order: has this specific issue ever been assigned before, does more than one rule in your list match its frames, and does the pattern you wrote match a frame Sentry counts as your application's own code. Those three questions cover the overwhelming majority of "my ownership rule stopped working" reports, and none of them require touching the rule itself.
How a match resolves
Sentry's ownership rules documentation defines four things a rule can match against: a file path, a module name, a request URL, or an event tag. All four use Unix-style glob syntax, * for any run of characters and ? for one, not regex, which is its own quiet source of false confidence when someone writes a pattern that looks like it should anchor and doesn't.
The part that catches teams off guard is what happens when more than one rule matches the same issue. Sentry doesn't pick the most specific pattern, and it doesn't pick the first rule in your list. It evaluates code owners top to bottom, then ownership rules top to bottom, and assigns based on whichever rule is the last one that matches. If that final rule lists more than one owner, the issue goes to the first, leftmost name on the line. A rule you wrote to be an exception sitting above a broader catch-all rule loses to the catch-all every time, because the catch-all comes later in the list and later wins.
For example: a path:src/billing/* #payments-eng rule sitting above a broader path:src/services/* #platform-eng rule works fine right up until a refactor moves the billing code into src/services/billing/. The payments pattern stops matching anything, the platform pattern starts matching billing frames too, and because it's the later rule in the list, it becomes the last match on every billing issue from then on. Nothing errors or warns; the only sign is billing issues landing in the wrong channel until someone checks the rules by hand.
The three things that get diagnosed as "the rule is broken"
An issue that's already been touched stops listening to the rule entirely. Sentry's own behavior here is direct: once an issue has been assigned, whether a person did it manually or a rule did it automatically, future auto-assignment turns off for that issue. New events keep arriving, none of them re-trigger routing. This is the single most common false alarm, because the rule is working exactly as configured; it's just that the specific issue in front of you was manually reassigned three weeks ago and nobody remembers.
Glob patterns can match more than the literal pattern implies. In 2023, a **/*.css #ux-infra ownership rule was found to match issues with no CSS anywhere in the stack trace, because the wildcard expansion was more permissive than the pattern implied (getsentry/sentry#44854, fixed via getsentry/relay#1952). That specific bug closed in April 2023 and doesn't reproduce on current Sentry, but the habit it should leave you with still holds: if a rule seems to fire on everything or on nothing, test the literal pattern against a real frame path from a recent event rather than trusting the glob syntax by eye.
A fallback rule catching everything isn't proof the rule and another assignment setting are fighting each other. A team with suspect-commit assignment enabled and GitHub User Mappings configured spent months watching new issues land on a fallback ownership rule instead of the commit author (getsentry/sentry#83765). The cause wasn't rule priority: Sentry's suspect-commit matcher was checking only the raw commit-author email from the GitHub API and never consulting the User Mapping, so an anonymized GitHub noreply email never resolved to a Sentry user. Sentry closed the issue in September 2025, and commit authors can now match by email or by User Mapping (getsentry/sentry#99273). The lesson outlives the bug: a fallback assignment doesn't tell you which setting "won," it can mean the other one has a matching gap of its own.
On top of those three, Sentry's docs note that auto-assignment can be skipped outright during a burst of new issues and retried later, so a flood of errors from a bad deploy is exactly the moment routing looks least reliable, right when you need it most.
Where checking rules by hand stops scaling
Catching this once, for one project, with two rules, is a ten-minute investigation once you know what to look for. It stops being that simple past a certain size:
- A refactor doesn't announce which rules it breaks. Nothing in Sentry flags a rule whose pattern stopped matching anything; it just quietly stops assigning, and the only signal is a growing pile of misrouted issues nobody's connected yet.
- Rule order is invisible unless someone opens the settings page. "Last match wins" means the actual routing behavior for any given issue depends on where a rule sits in a list most engineers never look at after writing it.
- None of this correlates against what the error is costing. Even a correctly routed issue only tells you which team owns the code. It says nothing about which customers hit it, whether it's the same complaint already sitting in a support ticket, or whether it's worth interrupting anyone's day for.
That last gap is the one worth being honest about: fixing the pattern gets the next issue to the right team, but it doesn't tell that team who's affected or whether the same problem already showed up somewhere else. That's a different layer than routing, and it's the layer Modem works on. Modem's Sentry integration reads issues, stack traces, and sample events alongside your Slack, support, and call transcripts, and surfaces which customers and companies are actually hitting an error, in one prioritized view instead of a stack trace with no context. With your approval, it can resolve, assign, or reprioritize the issue using that context, but it doesn't touch the ownership rule itself: a refactor that breaks src/billing/* still breaks it whether or not Modem is installed. We build Modem, so weigh that against just fixing the pattern. Once an issue is correctly assigned, which customers actually hit it is usually the next useful question, and it's one ownership rules were never built to answer.
The smallest version you can start this week
Pick your project's most-relied-on ownership rule, pull a recent issue it's supposed to cover, and check two things: whether that issue has ever been assigned before, and whether any rule below it in the list also matches. That single check catches both failure modes behind most misrouting, and it takes less time than opening this guide did.
