Next.js changed how we build full-stack React apps — server components, API routes, and edge functions all in one codebase. But they also changed where errors can hide. A TypeError on the client looks different from a database error on the server, and a race condition in a server component can silently fail without reaching your app's error boundaries. Next.js error tracking means capturing all of them: render errors, server-side exceptions, API route failures, and middleware panics, with stack traces that map back to your real source code.
This guide sets up production-grade error tracking across your entire Next.js app using the Sentry SDK pointed at LightTrace.
Install and initialize the Sentry SDK
Start by adding the Sentry SDK for Node.js and React. Because LightTrace is Sentry-SDK-compatible, you use the standard packages and change only the dsn.
npm install @sentry/nextjs
Sentry provides a Next.js-specific package that handles both server and client configuration automatically. Initialize it in your root layout:
// app/layout.tsx
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "https://<key>@your-lighttrace-host/1",
environment: process.env.NODE_ENV,
release: `web@${process.env.NEXT_PUBLIC_APP_VERSION || "0.0.1"}`,
tracesSampleRate: 1.0,
});
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
The @sentry/nextjs package automatically instruments server components, API routes, and the client runtime. It installs global handlers for both server-side exceptions and browser errors, so uncaught exceptions start flowing to LightTrace immediately.
The @sentry/nextjs package handles the split between client and server code automatically — you don't need separate init calls or configuration files. It detects your app's environment and wires up the right handlers.
Catch client-side render errors with an Error Boundary
Server components can throw, but client components need an Error Boundary to surface render-phase errors. Sentry ships a ready-made boundary that reports to LightTrace and shows a fallback UI:
// app/error.tsx
"use client";
import * as Sentry from "@sentry/nextjs";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
// Manually report if needed (already captured, but useful for context)
if (error) {
Sentry.captureException(error);
}
return (
<div style={{ padding: "2rem" }}>
<h1>Something went wrong</h1>
<button onClick={reset}>Try again</button>
</div>
);
}
Next.js's error.tsx boundary catches render errors in any child component within a route segment. The exception is automatically reported; you can optionally call Sentry.captureException() for additional context.
Place error.tsx files at multiple levels in your route tree. An error boundary in app/error.tsx catches everything, but a boundary in app/(dashboard)/error.tsx catches only dashboard errors, so a crash in one section doesn't blank your entire app.
Upload source maps so stack traces are readable
In production, Next.js minifies your code, so a raw stack trace points to bundle-abc123.js:1:45923. Source maps map that back to your real .tsx files. Enable them and upload on each deploy:
// next.config.ts
import { NextConfig } from "next";
const config: NextConfig = {
productionBrowserSourceMaps: true,
};
export default config;
This generates source maps for client-side code. For the full setup — uploading them in CI so every release has readable traces — follow the Next.js source maps guide, which includes ready-to-use CI workflows.
Capture context and breadcrumbs for faster debugging
Raw stack traces are a starting point. The real speed-up comes from context — who hit the error, what they did, which release introduced it, and what requests or database calls preceded it. Set the user and breadcrumbs:
// In a server action or API route
import * as Sentry from "@sentry/nextjs";
Sentry.setUser({ id: userId, email: userEmail });
Sentry.addBreadcrumb({
category: "database",
message: "Fetching user profile",
level: "info",
data: { userId },
});
On the client side, capture breadcrumbs for page navigation and user actions:
// In a client component
Sentry.addBreadcrumb({
category: "user-action",
message: "Clicked submit on form",
level: "info",
});
Every error that arrives at LightTrace now carries the breadcrumb trail of events that led to it, so you can reproduce the exact path instead of guessing.
Monitor server-side failures in API routes and middleware
API routes throw for many reasons — database errors, validation failures, third-party API timeouts. Sentry wraps your API handlers automatically, but you can add richer context:
// app/api/checkout/route.ts
import * as Sentry from "@sentry/nextjs";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const userId = request.headers.get("x-user-id");
Sentry.setUser({ id: userId });
try {
const body = await request.json();
// your checkout logic here
return NextResponse.json({ success: true });
} catch (error) {
Sentry.captureException(error);
return NextResponse.json({ error: "Checkout failed" }, { status: 500 });
}
}
Middleware errors are trickier because middleware has limited access to request context, but Sentry captures them automatically. If you need to add custom context in middleware, attach it via headers:
// middleware.ts
import { NextRequest } from "next/server";
import * as Sentry from "@sentry/nextjs";
export function middleware(request: NextRequest) {
Sentry.addBreadcrumb({
category: "middleware",
message: `${request.method} ${request.nextUrl.pathname}`,
level: "info",
});
// your middleware logic
}
export const config = { matcher: ["/((?!_next).*)"] };
Common Next.js errors worth watching
A few errors are specific to how Next.js works:
- Hydration mismatches — server and client rendered different HTML. These surface as "Text content does not match server" or "Expected the server HTML to contain" warnings. Check for browser-only APIs like
windowbeing used during render, or dates/timezones that differ between server and client. See React hydration errors for the full diagnosis. - Async/await in render — if you're using server components with async/await, errors in the promise reject silently unless they're inside a try/catch. Always wrap async operations.
- Missing
"use client"directives — if you import a hook or browser API in a server component and forgot the"use client"directive, you'll get a cryptic error. The React error boundary guide has more on the server/client boundary.
With error tracking, these stop being mystery warnings in the terminal and become actionable issues with a stack trace and a user count.
Next steps
That's the full setup: SDK initialized on server and client, error boundaries catching render crashes, source maps making traces readable, and context making them fast to fix. For the broader context on how errors flow through your app, see how to add error tracking to any app and JavaScript error monitoring for the client-side layer.
Start tracking errors in minutes
Point the Sentry SDK at LightTrace and start capturing Next.js errors across server components, API routes, and the client — readable stack traces in minutes, free up to 5,000 events a month.
Next.js's full-stack architecture is powerful, but it means errors can live in server components, middleware, API routes, or client code. Error tracking ensures every path is covered, so you see the bugs before your users do.