Sentry Error Monitoring
ChimerAI ships with a ready-to-use Sentry integration for error tracking, performance monitoring, and session replay — covering browser, server, and edge runtimes out of the box.
Installation
npx chimerai add sentry
Files scaffolded
| File | Purpose |
|---|---|
sentry.client.config.ts | Browser error tracking + Session Replay |
sentry.server.config.ts | API routes + Server Components |
sentry.edge.config.ts | Edge Runtime (middleware) |
instrumentation.ts | Next.js hook — loads the right config per runtime |
app/global-error.tsx | Global error boundary with automatic Sentry reporting |
Dependencies installed automatically:
@sentry/nextjs ^8.0.0
ChimerAI vs. Sentry Wizard
Sentry's own onboarding recommends running their interactive wizard:
# NOT needed when using ChimerAI
npx @sentry/wizard@latest -i nextjs --saas --org <org> --project <project>
Do not run the wizard in a ChimerAI app — it would overwrite the files ChimerAI already generated.
ChimerAI's chimerai add sentry produces the same output as the wizard, plus it is pre-wired to ChimerAI's auth and API conventions. The only steps the wizard does that ChimerAI does not automate are:
| Step | Wizard | ChimerAI |
|---|---|---|
| Scaffold config files | ✅ | ✅ |
Add @sentry/nextjs dependency | ✅ | ✅ |
Add .env placeholders | ✅ | ✅ |
Wrap next.config.js with withSentryConfig | ✅ automatic | ⚠️ manual (see below) |
| Create Sentry project on sentry.io | browser flow | manual |
In short: run chimerai add sentry, then follow the two manual steps in Setup below.
Setup
1. Create a Sentry project
Go to sentry.io → New Project → Next.js.
Copy the DSN from Settings → Client Keys (DSN).
2. Add environment variables
# .env.local
NEXT_PUBLIC_SENTRY_DSN=https://abc123@o123456.ingest.sentry.io/789
SENTRY_AUTH_TOKEN=sntrys_... # Settings → Auth Tokens
SENTRY_ORG=your-org-slug
SENTRY_PROJECT=your-project-slug
SENTRY_AUTH_TOKEN is only needed for source map uploads during pnpm build. Without it, Sentry works but stack traces show minified code in production.
3. Wrap next.config.js (manual step)
// next.config.js
import { withSentryConfig } from '@sentry/nextjs';
const nextConfig = { /* your existing config */ };
export default withSentryConfig(nextConfig, {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
hideSourceMaps: true, // don't expose source maps in the browser bundle
silent: !process.env.CI,
disableLogger: true,
});
4. Test your setup
pnpm build && pnpm start
Open your app, trigger an error (see Testing), and check the Sentry dashboard.
How it works
Sentry is disabled in development by default (enabled: process.env.NODE_ENV === 'production'). This prevents your local dev noise from polluting your production error feed. All three configs follow this rule.
Browser crash → sentry.client.config.ts → Sentry Issues
API route throws → sentry.server.config.ts → Sentry Issues
middleware throws → sentry.edge.config.ts → Sentry Issues
Unhandled page err → app/global-error.tsx → Sentry Issues (+ "Something went wrong" UI)
ChimerAI-specific usage patterns
The scaffolded config catches all unhandled errors automatically. The patterns below are for adding context so errors are actionable — not just "something failed" but "gpt-4o rate-limited user abc@example.com during a RAG query."
Identify the current user
Add this once after a successful login — Sentry attaches user info to every subsequent event:
// e.g. in your SessionProvider or a useEffect after session load
import * as Sentry from '@sentry/nextjs';
if (session?.user) {
Sentry.setUser({
id: session.user.id,
email: session.user.email ?? undefined,
});
}
// On logout:
Sentry.setUser(null);
With this in place, every error in the Sentry dashboard shows which user was affected — essential for Enterprise support workflows.
AI provider errors
The chat stream route is the highest-value place to add Sentry context. Provider rate limits, token overflows, and API outages all surface here:
// app/api/v1/chat/stream/route.ts
import * as Sentry from '@sentry/nextjs';
try {
// ... your existing streaming logic
} catch (error) {
Sentry.withScope((scope) => {
scope.setTag('provider', provider.type); // 'openai' | 'anthropic' | 'ollama'
scope.setTag('model', modelId); // 'gpt-4o' | 'claude-3-5-sonnet'
scope.setExtra('userId', auth.userId);
scope.setExtra('conversationId', conversationId);
Sentry.captureException(error);
});
// re-throw or return error response as usual
throw error;
}
This lets you filter in Sentry by provider or model — for example "show me all errors from Anthropic in the last 24h."
Provider sync failures
When a provider sync fails (network error, invalid API key, rate limit), capture with context:
// app/api/providers/[id]/sync/route.ts
import * as Sentry from '@sentry/nextjs';
try {
// ... sync logic
} catch (error) {
Sentry.withScope((scope) => {
scope.setTag('provider_type', provider.type);
scope.setExtra('provider_id', provider.id);
scope.setLevel('warning'); // sync failure is annoying, not critical
Sentry.captureException(error);
});
return NextResponse.json({ error: 'Sync failed' }, { status: 500 });
}
Billing webhook failures
Missed webhooks from LemonSqueezy or Stripe mean subscriptions don't activate. These should be errors, not warnings:
// app/api/billing/webhook/route.ts
import * as Sentry from '@sentry/nextjs';
try {
// ... webhook processing
} catch (error) {
Sentry.withScope((scope) => {
scope.setTag('billing_provider', 'lemonsqueezy'); // or 'stripe'
scope.setTag('webhook_event', event.type);
scope.setExtra('subscription_id', event.data?.id);
scope.setLevel('error');
Sentry.captureException(error);
});
// Return 500 so LemonSqueezy retries the webhook
return NextResponse.json({ error: 'Webhook failed' }, { status: 500 });
}
Why this matters: If you return 200 from a failed webhook handler, the billing provider won't retry. Return 500 so you get a retry AND a Sentry alert.
RAG pipeline errors
Embedding generation and vector search can fail silently. Make failures visible:
// app/api/v1/rag/query/route.ts
import * as Sentry from '@sentry/nextjs';
try {
const chunks = await vectorSearch(query, sessionId);
// ...
} catch (error) {
Sentry.withScope((scope) => {
scope.setTag('rag_stage', 'vector_search'); // or 'embedding_generation'
scope.setExtra('query_length', query.length);
scope.setExtra('session_id', sessionId);
Sentry.captureException(error);
});
// Graceful fallback: answer without context
return streamWithoutContext(messages);
}
Non-error tracking with captureMessage
Not every notable event is an exception. Use captureMessage for important state changes you want visibility into:
import * as Sentry from '@sentry/nextjs';
// Admin actions worth auditing in Sentry
Sentry.captureMessage('Provider API key rotated', {
level: 'info',
tags: { provider: provider.type },
extra: { provider_id: provider.id, changed_by: session.user.email },
});
// Soft limits hit (not errors, but worth knowing)
Sentry.captureMessage('User approaching credit limit', {
level: 'warning',
extra: { userId, creditsRemaining: balance },
});
Levels: debug → info → log → warning → error → fatal
Filtering noise
Not every error deserves an alert. Configure beforeSend in sentry.client.config.ts to drop known non-issues:
// sentry.client.config.ts
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
// ...
beforeSend(event, hint) {
const error = hint?.originalException;
// Ignore user-canceled fetch requests (e.g. navigating away mid-stream)
if (error instanceof Error && error.message === 'The user aborted a request.') {
return null;
}
// Ignore known Next.js hydration warnings
if (event.message?.includes('Hydration failed')) {
return null;
}
return event;
},
});
On the server side, add similar filters to sentry.server.config.ts — for example ignoring 404s:
// sentry.server.config.ts
beforeSend(event) {
// Don't alert on 404 Not Found
if (event.contexts?.response?.status_code === 404) {
return null;
}
// Strip auth headers (already in the scaffold — keep this)
if (event.request?.headers) {
delete event.request.headers['authorization'];
delete event.request.headers['cookie'];
}
return event;
},
Setting up alerts
In the Sentry dashboard → Alerts → Create Alert. Recommended rules for ChimerAI apps:
| Alert | Condition | Suggested threshold |
|---|---|---|
| AI provider down | tag:provider errors spike | > 10 errors in 5 min |
| Billing webhook failed | tag:billing_provider errors | Any single occurrence |
| Global error rate spike | All errors combined | > 50 errors in 10 min |
| New issue | First occurrence of any new issue | Immediately (useful in early production) |
Set the notification channel to email or Slack under Settings → Integrations.
Session Replay
Session Replay records what the user was doing when an error occurred — clicks, scrolls, network requests. It's configured in sentry.client.config.ts:
replaysSessionSampleRate: 0.1, // record 10% of all sessions
replaysOnErrorSampleRate: 1.0, // record 100% of sessions with errors
Privacy: Replay automatically masks all <input> fields. For additional masking (e.g. chat messages you don't want recorded):
// Add data attribute to sensitive elements
<div data-sentry-mask>
{message.content}
</div>
View replays in Sentry → Replays. Click any error in Issues → "View Replay" to see exactly what the user did.
Testing
To verify Sentry is working without deploying to production, temporarily enable it in development:
// sentry.client.config.ts — temporary test change
enabled: true, // revert after testing!
Then trigger a test event:
// In any Client Component or Browser DevTools console:
import * as Sentry from '@sentry/nextjs';
Sentry.captureMessage('Sentry test — delete me', 'info');
Check Sentry dashboard → Issues → the test event should appear within ~30 seconds.
Remember to revert enabled: true before committing.
Source maps in production
Source maps allow Sentry to show readable stack traces (original TypeScript line numbers) instead of minified bundle offsets. They are uploaded during pnpm build when SENTRY_AUTH_TOKEN is set.
Without source maps: at r (/_next/static/chunks/app/page-abc123.js:1:4892)
With source maps: at ChatPage (app/dashboard/chat/page.tsx:47:12)
For Vercel deployments, add all four Sentry env vars to your Vercel project settings (Settings → Environment Variables). Vercel runs pnpm build in CI where SENTRY_AUTH_TOKEN is available, so maps upload automatically on every deploy.