Next.js Error Monitoring in 2026: Sentry Integration, Error Boundaries, Source Maps, and Alerts
Set up production error monitoring for Next.js: Sentry SDK integration, App Router error boundaries, source map upload, performance tracing, custom context, and alert configuration.
Next.js Error Monitoring in 2026: Sentry Integration, Error Boundaries, Source Maps, and Alerts
Production errors in Next.js are split across three runtimes: the browser (client components), Node.js (server components and API routes), and edge middleware. Without proper error monitoring, you get cryptic stack traces pointing to minified bundle code, no user context, and no way to know if a bug is affecting 1 user or 10,000.
This post covers Sentry integration with Next.js App Router: SDK setup, error.tsx error boundaries, source map upload for readable stacks, user context, custom tags, performance tracing, and alert configuration.
Installation
npx @sentry/wizard@latest -i nextjs
# Or manually:
npm install @sentry/nextjs
Sentry Configuration Files
// sentry.client.config.ts โ browser (Client Components)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
// Performance monitoring
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
// 10% of transactions in production (adjust based on volume)
// Session replay (records user interactions before error)
replaysSessionSampleRate: 0.05, // 5% of sessions
replaysOnErrorSampleRate: 1.0, // 100% of sessions with errors
integrations: [
Sentry.replayIntegration({
maskAllText: true, // Privacy: mask all text in replay
blockAllMedia: true, // Privacy: block images/video
}),
Sentry.browserTracingIntegration(),
],
// Filter noise
ignoreErrors: [
"ResizeObserver loop limit exceeded",
"Non-Error promise rejection captured with value: Object Not Found Matching Id",
/^Loading chunk \d+ failed/, // Ignore chunk load errors (usually transient)
],
beforeSend(event, hint) {
// Don't send errors from browser extensions
if (event.exception?.values?.[0]?.stacktrace?.frames?.some(
(f) => f.filename?.includes("extensions/")
)) {
return null;
}
return event;
},
});
// sentry.server.config.ts โ Node.js (Server Components, API routes)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.2 : 1.0,
// Integrations
integrations: [
Sentry.prismaIntegration(), // Capture Prisma query errors
Sentry.httpIntegration({ tracing: true }),
],
// Capture unhandled promise rejections
autoSessionTracking: true,
});
// sentry.edge.config.ts โ Edge Runtime (middleware)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 0.1,
});
๐ Looking for a Dev Team That Actually Delivers?
Most agencies sell you a project manager and assign juniors. Viprasol is different โ senior engineers only, direct Slack access, and a 5.0โ Upwork record across 100+ projects.
- React, Next.js, Node.js, TypeScript โ production-grade stack
- Fixed-price contracts โ no surprise invoices
- Full source code ownership from day one
- 90-day post-launch support included
Next.js Config: Source Maps
// next.config.ts
import { withSentryConfig } from "@sentry/nextjs";
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// ... your config
};
export default withSentryConfig(nextConfig, {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
// Upload source maps during build (requires SENTRY_AUTH_TOKEN)
authToken: process.env.SENTRY_AUTH_TOKEN,
// Hide source maps from browser (security)
hideSourceMaps: true,
// Disable Sentry CLI telemetry
telemetry: false,
// Automatically instrument Server Components and route handlers
autoInstrumentServerFunctions: true,
autoInstrumentMiddleware: true,
autoInstrumentAppDirectory: true,
// Suppress build output (optional)
silent: !process.env.CI,
});
App Router Error Boundaries
// app/error.tsx โ Client-side error boundary for the root layout
"use client";
import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Report to Sentry (includes stack trace + user context already set)
Sentry.captureException(error, {
tags: { errorBoundary: "root", digest: error.digest },
});
}, [error]);
return (
<html>
<body>
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="max-w-md w-full text-center px-4">
<div className="text-5xl mb-4">โ ๏ธ</div>
<h2 className="text-xl font-semibold text-gray-900 mb-2">
Something went wrong
</h2>
<p className="text-gray-500 text-sm mb-6">
Our team has been notified and is looking into it.
{error.digest && (
<span className="block mt-1 font-mono text-xs text-gray-400">
Error ID: {error.digest}
</span>
)}
</p>
<button
onClick={reset}
className="px-6 py-2.5 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700"
>
Try again
</button>
</div>
</div>
</body>
</html>
);
}
// app/dashboard/error.tsx โ Scoped error boundary (just the dashboard section)
"use client";
import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";
import { AlertCircle } from "lucide-react";
export default function DashboardError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
Sentry.captureException(error, {
tags: { errorBoundary: "dashboard" },
});
}, [error]);
return (
<div className="flex items-center justify-center h-96">
<div className="text-center max-w-sm">
<AlertCircle className="h-10 w-10 text-red-400 mx-auto mb-3" />
<h3 className="text-base font-medium text-gray-900 mb-1">
Failed to load dashboard
</h3>
<p className="text-sm text-gray-500 mb-4">
{error.message || "An unexpected error occurred"}
</p>
<button
onClick={reset}
className="px-4 py-2 bg-gray-900 text-white rounded-lg text-sm"
>
Retry
</button>
</div>
</div>
);
}
๐ Senior Engineers. No Junior Handoffs. Ever.
You get the senior developer, not a project manager who relays your requirements to someone you never meet. Every Viprasol project has a senior lead from kickoff to launch.
- MVPs in 4โ8 weeks, full platforms in 3โ5 months
- Lighthouse 90+ performance scores standard
- Works across US, UK, AU timezones
- Free 30-min architecture review, no commitment
User Context and Custom Tags
// lib/sentry/context.ts โ Set user context after authentication
import * as Sentry from "@sentry/nextjs";
export function setSentryUser(user: {
id: string;
email: string;
role: string;
workspaceId?: string;
}) {
Sentry.setUser({
id: user.id,
email: user.email,
// Do NOT include sensitive fields (no phone, no address)
});
Sentry.setTag("user.role", user.role);
Sentry.setTag("workspace.id", user.workspaceId ?? "none");
}
// Call in your auth provider or layout
// After successful auth session load:
import { auth } from "@/auth";
export default async function AppLayout({ children }: { children: React.ReactNode }) {
const session = await auth();
if (session?.user) {
// Server Components can set Sentry scope too
Sentry.setUser({ id: session.user.id, email: session.user.email });
}
return <>{children}</>;
}
Capturing Errors Manually
// lib/api/error-handler.ts
import * as Sentry from "@sentry/nextjs";
export function captureAPIError(
err: unknown,
context: {
route: string;
method: string;
workspaceId?: string;
userId?: string;
}
) {
Sentry.withScope((scope) => {
scope.setTag("route", context.route);
scope.setTag("method", context.method);
scope.setTag("workspace", context.workspaceId ?? "unknown");
scope.setContext("request", {
route: context.route,
method: context.method,
userId: context.userId,
});
Sentry.captureException(err);
});
}
// Usage in API route:
export async function POST(req: NextRequest) {
try {
// ... handle request
} catch (err) {
captureAPIError(err, {
route: "/api/orders",
method: "POST",
workspaceId: ctx?.workspaceId,
userId: ctx?.userId,
});
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
}
Performance Tracing
// lib/sentry/tracing.ts โ Custom transaction spans
import * as Sentry from "@sentry/nextjs";
// Wrap a slow operation in a span for tracing
export async function traced<T>(
name: string,
op: string,
fn: () => Promise<T>
): Promise<T> {
return Sentry.startSpan({ name, op }, fn);
}
// Usage:
const result = await traced("generateInvoicePDF", "pdf.generate", async () => {
return generatePDF(invoiceData);
});
// Mark important transactions
Sentry.setMeasurement("invoice.line_items", invoice.items.length, "none");
Alert Configuration (Sentry UI)
Set up these alerts in Sentry project settings:
# Alert rules to configure in Sentry:
- name: "Error rate spike"
condition: event count > 100 in 5 minutes
actions: [email, Slack #alerts]
filter: level = error
- name: "New error type"
condition: first seen (new issue)
actions: [email, Slack #alerts]
filter: level = error AND environment = production
- name: "High p95 latency"
condition: p95 transaction duration > 2000ms
actions: [Slack #perf-alerts]
- name: "Critical route down"
condition: error rate > 50% in 1 minute
filter: transaction = /api/checkout OR /api/auth
actions: [PagerDuty, Slack #incidents]
Cost and Timeline
| Component | Timeline | Cost (USD) |
|---|---|---|
| Sentry SDK setup (3 configs) | 0.5 day | $300โ$500 |
| Error boundaries (root + scoped) | 0.5 day | $300โ$500 |
| Source map upload configuration | 0.5 day | $200โ$400 |
| User context + custom tags | 0.5 day | $300โ$500 |
| Alert configuration | 0.5 day | $200โ$400 |
| Full error monitoring setup | 3โ5 days | $2,500โ$4,000 |
Sentry pricing: Free tier covers 5K errors/month. Team plan ($26/month) covers 50K errors and adds performance monitoring.
See Also
- Next.js App Router Caching โ Cache-related errors and debugging
- React Error Boundaries โ Client-side error boundary patterns
- AWS CloudWatch Observability โ Server-side metrics alongside Sentry
- TypeScript Error Handling โ Typed errors that integrate with Sentry
Working With Viprasol
We set up production error monitoring for Next.js applications โ from Sentry SDK configuration through custom alert rules, source map pipelines, and user context enrichment. Our team has configured Sentry for apps handling millions of monthly users, tuning sampling rates and alert thresholds to avoid noise while catching real issues.
What we deliver:
- Sentry SDK for all three Next.js runtimes (client, server, edge)
- Source map upload via
withSentryConfig(readable production stacks) - Root and scoped
error.tsxboundaries with Sentry reporting - User context and workspace tags on every error event
- Alert rules: new errors, rate spikes, critical route failures
Explore our web development services or contact us to set up error monitoring for your Next.js application.
About the Author
Viprasol Tech Team
Custom Software Development Specialists
The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.
Need a Modern Web Application?
From landing pages to complex SaaS platforms โ we build it all with Next.js and React.
Free consultation โข No commitment โข Response within 24 hours
Need a custom web application built?
We build React and Next.js web applications with Lighthouse โฅ90 scores, mobile-first design, and full source code ownership. Senior engineers only โ from architecture through deployment.