How to find out which customers hit a Sentry error
Open the issue, and Sentry shows you "14 users affected." Open the tags on that issue, and if you've called setUser() in your SDK, you can see the individual user.id, user.email, or user.username values behind that number. What Sentry can't tell you is which of those users are on your enterprise plan, which are up for renewal next month, or whether they're all from the same account. Sentry tracks users. It has no concept of a company.
Getting from "14 users" to "which customers" takes two things: user context that's actually being set on your events, and something outside Sentry that knows which user belongs to which account. Here's how each piece works, and where the manual version stops being fast enough.
Step 1: confirm you're capturing user identity at all
Sentry's user context docs are explicit that this isn't automatic: you call Sentry.setUser({ id, email, username }) yourself, typically right after your app knows who's logged in. Skip that call and every event on the issue shows no user at all, no matter how much traffic the endpoint gets.
This is the step that quietly breaks. Auth flows change, a new client gets added that never wires up the SDK, or setUser() runs before the session is hydrated and fires with an empty object. Before trusting an issue's "affected users" count, spot check a few recent events and confirm the user field is populated. If it's empty on any meaningful fraction of events, everything downstream of this guide is working from a fraction of the real picture.
Step 2: pull the affected users off the issue
Once identity is attached, Sentry's search syntax treats user.id, user.email, and user.username as first-class searchable fields. From an issue, filter by user.email:* to see distinct values, or search across your whole project for user.email:jsmith@example.com to find every issue a specific person has hit.
That gets you a list of identifiers. It does not get you a list of customers, because nothing in that list says which company each email belongs to. A support engineer looking at jsmith@example.com, dana@example.org, and sam@example.org has to already know, or go look up, that two of those three are the same account.
Step 3: attach an account identifier yourself, if you can
If your app knows the customer's company at the point where errors originate, Sentry's context and tags let you attach it directly: Sentry.setTag('account_id', org.id) alongside setUser(). Tags are searchable the same way user fields are, so account_id: plus the org's own identifier becomes a valid filter once it's wired up.
This is the fix for teams that control the client and have a stable org identifier available at error time. It's also extra instrumentation to add and keep current as your auth model changes, and it only covers errors captured after you ship it. Issues from last month still only have user IDs.
Filtering by one account still leaves the rest of the list unread
A new issue fires overnight, and the question waiting for you in the on-call channel isn't "what broke," it's "is this hitting the account that renews this week." Sentry answers half of it. Open the issue, read the affected-users count at the top, then filter the issue's events with user.email: plus that account's mail domain. Matching events come back, and you can say with certainty that the account is affected.
What you cannot say is anything else. The matches tell you that some of that account's users hit the error, not whether that is the account's whole team or a slice of it. The users who did not match are still unattributed, so any other at-risk account sitting in the remainder stays invisible until you paste every remaining address into a spreadsheet and look each one up against the customer list. And the symptom someone at that account already described in a shared Slack channel or a support ticket lives in a different system entirely; nothing on the issue tells you whether that report and this stack trace are the same bug, or two bugs that happen to throw alike.
So you answer the urgent half in the channel, then spend the rest of the lookup doing the join by hand. Sentry caught the error and preserved the identifiers, which is its job. The identifier-to-account join is yours, and it isn't saved anywhere for whoever asks the same question about the next issue.
Where the manual cross-reference stops working
The setup above scales fine for one issue and one urgent question. It breaks down predictably:
- The lookup doesn't persist. The answer lives in a Slack reply. The next engineer who touches this issue redoes the same email-to-company matching from scratch.
- Sentry's user list and your support/sales conversations are separate systems. Knowing which users from one account hit the bug doesn't tell you what someone there already said about it in Slack, or whether a support ticket describes the same symptom in different words.
- It doesn't scale past a handful of affected users. Fourteen users across an unknown number of accounts means fourteen manual lookups, every time, for every issue that matters enough to ask about.
At that volume, cross-referencing errors against account data stops being a five-minute favor and becomes a standing job nobody signed up for. It's also the layer Modem works on: Modem's Sentry integration reads issues, stack traces, and the user identifiers on them, resolves each one to a person and the company they belong to, and shows what that same account has said elsewhere (a Slack thread, a support ticket, a call transcript) next to the error. The question of whether a given account is affected becomes a lookup instead of a spreadsheet exercise, because the person-to-company join already happened before anyone asked. We build Modem. Judge it on whether the mechanism matches your setup, not on our description, and against the comparison in our roundup of tools that connect Sentry errors to customer feedback, which covers four other approaches to the same gap.
The underlying idea, a graph that keeps people linked to their companies and their companies linked to what they've said, is covered on its own in what a customer context graph is. None of this replaces setUser(); Modem still needs Sentry to have captured an identifier in the first place, so step 1 above stays your job regardless of what reads the data afterward.
Confirm setUser() fires on every authenticated path
Confirm setUser() fires on every authenticated request path, not just the main one. Then, for the next issue with more than a handful of affected users, do the email-to-company match once and write the account list into the issue as a comment before you close it. That alone means the next engineer who opens it isn't starting from zero.
