Sentry Error Tracking
Right now, your deployed app's errors go nowhere. A user hits a crash, sees a blank screen, closes the tab, and the only record of it is their opinion of you. Error tracking is how production tells you what broke before users bother to, and Sentry is the standard tool for it. The install is genuinely five minutes. The five minutes is also where most people stop, and a stopped-at-install Sentry is nearly worthless.
Here's why. Production JavaScript is minified, so without sourcemaps every stack trace reads like t is not a function at a.js:1:48213, which tells you a thing broke somewhere in your app, a fact you already had. Without releases, Sentry can't tell you which deploy introduced the error, which is usually the single most valuable clue, because "what did we just ship" is the first question anyway. And without alert rules, errors pile up in a dashboard nobody opens; you find out about the crash from a user email, which is the exact outcome the tool exists to prevent.
So this spec treats sourcemaps, releases, and alerts as part of the install, not as advanced options, and it adds the two hygiene items that keep Sentry useful past week one: scrubbing user data you shouldn't be storing, and filtering the noise (browser extensions, bots, ad-blocker fallout) that otherwise trains you to ignore the feed. An alert channel you've learned to ignore is the same as no alert channel, with worse morale.
Prerequisites
- A Sentry account (free tier is fine) with a project created for your platform: grab the DSN.
- A Sentry auth token with `project:releases` scope, stored as a CI secret, never in the repo.
- Deploys that run through CI or a build step you control (sourcemap upload hooks in there).
# Spec: Sentry error tracking
Wire Sentry into [app name] so production errors arrive with readable stack
traces, are tied to the release that introduced them, and page a human.
"Installed" is not done; the verification list at the bottom is done.
## Stack
- Framework: [e.g., Next.js 14 (use @sentry/nextjs) / Express / FastAPI]
- Deploys via [Vercel / GitHub Actions / other CI]
- Errors happen in: [browser / server / both — instrument every runtime,
a browser-only setup misses every API route failure]
## Environment variables and secrets
```bash
NEXT_PUBLIC_SENTRY_DSN=https://...ingest.sentry.io/... # DSN is client-safe
SENTRY_ENVIRONMENT=production # and 'preview', 'development'
SENTRY_AUTH_TOKEN=sntrys_... # CI secret ONLY: uploads sourcemaps.
# Never in the repo, never in client env.
```
## Init (every runtime)
- `environment: SENTRY_ENVIRONMENT` so production issues aren't buried
under dev noise; filter every view and alert to production.
- `release: [git SHA, injected at build time]` — same value in client and
server init, and the same value the sourcemap upload uses.
- `tracesSampleRate: [0.1]` to start. Performance data is nice; a surprise
bill or a blown free-tier quota is not. Raise it on purpose later.
- Dev: leave the DSN unset locally so nothing reports. Local errors belong
in your terminal, not the production dashboard.
## Sourcemaps and releases (the part everyone skips)
- Use the SDK's build integration ([withSentryConfig / sentry-cli]) to
upload sourcemaps during the production build in CI, authenticated by
SENTRY_AUTH_TOKEN, tagged with the same release as the init.
- Do not ship public sourcemaps to end users; upload to Sentry, delete from
the deploy output (the integrations do this by default — leave it on).
- Associate commits with the release (`setCommits` / the CI flag) so an
issue page shows the commits between "worked" and "broke."
## Context that makes issues debuggable
- After login: `Sentry.setUser({ id: user.id })`. The id, not the email:
enough to count affected users and correlate with your own logs, without
copying PII into a third-party tool. Clear it on logout.
- `sendDefaultPii: false` (the default; do not flip it on).
- `beforeSend`: strip anything resembling tokens or secrets from event
data, and drop known noise:
```typescript
beforeSend(event, hint) {
const msg = hint?.originalException?.message ?? "";
// Browser-extension and network noise that isn't our bug:
if (/chrome-extension|ResizeObserver loop|Failed to fetch/.test(msg)) {
return null;
}
delete event.request?.cookies; // never useful, always sensitive
return event;
}
```
- Wrap the app in the SDK's error boundary with a real fallback screen:
"something broke, it's been reported" beats a white page.
## Alerts (a dashboard nobody opens is a diary)
Wire Sentry's [Slack / email] integration, then exactly these rules to
start — more rules than you'll triage is how feeds get muted:
1. New issue type in production -> [#alerts channel] immediately.
2. Regression (resolved issue returns) -> same channel. A regression means
a fix didn't hold; treat it as louder than a new bug, not quieter.
3. Any issue over [100] events/hour -> [the person on call].
Triage habit: every alert gets resolved, ignored-with-a-reason, or turned
into an issue in [tracker]. An alert channel that scrolls unread is off.
## Verification (before calling this done)
1. Deploy a route/button that throws `new Error("sentry-test-[date]")`.
Trigger it in production. The issue arrives within a minute.
2. The stack trace shows YOUR file names and line numbers, not minified
`a.js:1`. If not, the sourcemap upload or the release tag mismatch is
the bug; fix before proceeding.
3. The issue shows release [SHA] and the commit list.
4. The alert lands in [channel]. Resolve the issue, trigger the error
again, confirm the regression alert fires.
5. Throw from a SERVER route too; confirm it reports with the same release.
6. Remove the test route.Adaptation notes:
- Next.js on Vercel: the official wizard (
npx @sentry/wizard@latest -i nextjs) writes the config files, three init files for the three runtimes (client, server, edge); keep all of them or you'll silently miss whole classes of errors. Wizard first, then verify it against this spec, especially environment, release, andbeforeSend. - Python/FastAPI or plain Node backends: same spec minus browser sourcemaps; stack traces are readable natively, so releases, alerts, and scrubbing are the whole job.
- Wire your caught errors too:
Sentry.captureException(err)in catch blocks that swallow errors after logging. A payment webhook that catches, logs to nowhere, and returns 200 is a silent failure generator; those catches are exactly where tracking earns its keep. - Sentry's free tier caps events per month. The
beforeSendnoise filters and a modest sample rate are what keep a traffic spike from burning the quota mid-incident, which is the one moment you need headroom. - The mistake: verifying with a local test error, seeing it arrive, calling it done. Local has unminified code and no sourcemap problem to expose. The only test that counts is a production error with a readable trace, which is why step 2 of verification exists and why "the agent installed Sentry" is the beginning of done, not the end.