Manual Setup
Learn how to manually set up Sentry in your Next.js app and capture your first errors.
For the fastest setup, we recommend using the wizard installer.
You need:
Choose the features you want to configure, and this guide will show you how:
Want to learn more about these features?
Run the command for your preferred package manager to add the Sentry SDK to your application:
npm install @sentry/nextjs --save
Extend your app's default Next.js options by adding withSentryConfig
into your next.config.(js|mjs)
file:
next.config.js
const { withSentryConfig } = require("@sentry/nextjs");
const nextConfig = {
// Your existing Next.js configuration
};
// Make sure adding Sentry options is the last code to run before exporting
module.exports = withSentryConfig(nextConfig, {
org: "example-org",
project: "example-project",
// Only print logs for uploading source maps in CI
// Set to `true` to suppress logs
silent: !process.env.CI,
// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
});
Create three files in your application's root directory: sentry.client.config.(js|ts)
, sentry.server.config.(js|ts)
and sentry.edge.config.(js|ts)
. Add the following initialization code into each respective file:
Note
These files run in different environments (browser, server, edge) and are slightly different, so copy them carefully.
sentry.client.config.(js|ts)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
// Replay may only be enabled for the client-side
integrations: [Sentry.replayIntegration()],
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for tracing.
// We recommend adjusting this value in production
// Learn more at
// https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
tracesSampleRate: 1.0,
// Capture Replay for 10% of all sessions,
// plus for 100% of sessions with an error
// Learn more at
// https://docs.sentry.io/platforms/javascript/session-replay/configuration/#general-integration-configuration
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
});
Tip
Include your Data Source Name (DSN) directly in these files, or use a public environment variable like NEXT_PUBLIC_SENTRY_DSN
.
Create a Next.js Instrumentation file named instrumentation.(js|ts)
in your project root or inside the src
folder if you have one. Import your server and edge configurations, making sure that the imports point to your specific files:
instrumentation.(js|ts)
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("./sentry.server.config");
}
if (process.env.NEXT_RUNTIME === "edge") {
await import("./sentry.edge.config");
}
}
Next.js version <15 only
You need to enable the instrumentation hook by setting the experimental.instrumentationHook
to true
in your next.config.(js|mjs)
file.
To capture React render errors, you need to add error components for the App Router and the Pages Router.
Create or update the global-error.(tsx|jsx)
file to define a custom Next.js GlobalError component:
global-error.tsx
"use client";
import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";
export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
}) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<html>
<body>
{/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
<NextError statusCode={0} />
</body>
</html>
);
}
Requires @sentry/nextjs
version 8.28.0
or higher and Next.js 15.
To capture errors from nested React Server Components, use the onRequestError
hook in instrumentation.(js|ts)
and pass all arguments to the captureRequestError
function:
instrumentation.ts
import * as Sentry from "@sentry/nextjs";
export const onRequestError = Sentry.captureRequestError;
Need additional logic within `onRequestError`?
Create or update the _error.(tsx|jsx)
file to define a custom Next.js error page for the Pages Router like so:
_error.tsx
import * as Sentry from "@sentry/nextjs";
import type { NextPage } from "next";
import type { ErrorProps } from "next/error";
import Error from "next/error";
const CustomErrorComponent: NextPage<ErrorProps> = (props) => {
return <Error statusCode={props.statusCode} />;
};
CustomErrorComponent.getInitialProps = async (contextData) => {
// In case this is running in a serverless function, await this in order to give Sentry
// time to send the error before the lambda exits
await Sentry.captureUnderscoreErrorException(contextData);
// This will contain the status code of the response
return Error.getInitialProps(contextData);
};
export default CustomErrorComponent;
Requires @sentry/nextjs
SDK version 7.81.0
or newer.
To instrument Next.js Server Actions, wrap their content in withServerActionInstrumentation
, along with a name to describe your server action.
You can optionally pass form data and headers to record them, and configure the wrapper to record the Server Action responses:
import * as Sentry from "@sentry/nextjs";
import { headers } from "next/headers";
export default function ServerComponent() {
async function myServerAction(formData: FormData) {
"use server";
return await Sentry.withServerActionInstrumentation(
"myServerAction", // The name you want to associate this Server Action with in Sentry
{
formData, // Optionally pass in the form data
headers: headers(), // Optionally pass in headers
recordResponse: true, // Optionally record the server action response
},
async () => {
// ... Your Server Action code
return { name: "John Doe" };
},
);
}
return (
<form action={myServerAction}>
<input type="text" name="some-input-value" />
<button type="submit">Run Action</button>
</form>
);
}
Sentry can automatically provide readable stack traces for errors using source maps, requiring a Sentry auth token.
Update your next.config.(js|mjs)
file with the following options:
next.config.mjs
export default withSentryConfig(nextConfig, {
org: "example-org",
project: "example-project",
// Pass the auth token
authToken: process.env.SENTRY_AUTH_TOKEN,
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,
});
Alternatively, set the SENTRY_AUTH_TOKEN
environment variable in your .env
file:
.env
SENTRY_AUTH_TOKEN=sntrys_YOUR_TOKEN_HERE
Important
Make sure to keep your auth token secret and out of version control.
You can prevent ad blockers from blocking Sentry events using tunneling. Use the tunnelRoute
option to add an API endpoint in your application that forwards Sentry events to Sentry servers.
Update withSentryConfig
in your next.config.(js|mjs)
file with the following options:
next.config.mjs
export default withSentryConfig(nextConfig, {
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
// This can increase your server load as well as your hosting bill.
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-side errors will fail.
tunnelRoute: "/monitoring",
});
Complications with Next.js middleware
Client-side event recording will fail if your Next.js middleware intercepts the configured route. To prevent this, exclude the tunnel route by adding a negative matcher to your middleware like (?!monitoring-tunnel)
.
The SDK will automatically instrument API routes and server-side Next.js data fetching methods with error and tracing.
To disable the automatic instrumentation of API route handlers and server-side data fetching functions, set the autoInstrumentServerFunctions
to false
.
next.config.mjs
export default withSentryConfig(nextConfig, {
autoInstrumentServerFunctions: false,
});
With this option, under the hood, the SDK is using a webpack loader to wrap all your API route handlers and data fetching methods.
If the automatic instrumentation doesn't work for your use case, you can turn it off globally and choose to only wrap specific API route handlers or data fetching functions instead.
For API routes, use the wrapApiHandlerWithSentry
function:
pages/api/*
import { wrapApiHandlerWithSentry } from "@sentry/nextjs";
const handler = (req, res) => {
res.status(200).json({ name: "John Doe" });
};
export default wrapApiHandlerWithSentry(handler, "/api/myRoute");
For data fetching methods, use the following functions:
wrapGetInitialPropsWithSentry
forgetInitialProps
wrapGetServerSidePropsWithSentry
forgetServerSideProps
wrapGetStaticPropsWithSentry
forgetStaticProps
wrapErrorGetInitialPropsWithSentry
forgetInitialProps
in custom Error pageswrapAppGetInitialPropsWithSentry
forgetInitialProps
in customApp
componentswrapDocumentGetInitialPropsWithSentry
forgetInitialProps
in customDocument
components
If you want auto-instrumentation to apply by default, but want to exclude certain routes, use the excludeServerRoutes
option:
next.config.mjs
export default withSentryConfig(nextConfig, {
excludeServerRoutes: [
"/some/excluded/route",
"/excluded/route/with/[parameter]",
/^\/route\/beginning\/with\/some\/prefix/,
/\/routeContainingASpecificPathSegment\/?/,
],
});
Excluded routes can be specified either as regexes or strings. When using a string, make sure that it matches the route exactly, and has a leading slash but no trailing one.
To disable the automatic instrumentation of Next.js middleware, set the autoInstrumentMiddleware
option to false
.
next.config.mjs
export default withSentryConfig(nextConfig, {
autoInstrumentMiddleware: false,
});
If you want the Sentry SDK to be available in your server-side and not in client-side, you can simply delete sentry.client.config.js
. This will prevent webpack from pulling in the Sentry related files when generating the browser bundle. Similarly, to opt out of server-side SDK bundling, you can simply delete the sentry.server.config.js
and sentry.edge.config.js
files. Make sure to remove any imports of these files from instrumentation.ts
.
You can automatically create Cron Monitors in Sentry if you have configured Vercel cron jobs.
Update withSentryConfig
in your next.config.(js|mjs)
file with the following option:
next.config.mjs
export default withSentryConfig(nextConfig, {
automaticVercelMonitors: true,
});
Automatic Vercel cron jobs instrumentation currently only supports the Pages Router. App Router route handlers are not yet supported.
You can capture React component names to see which component a user clicked on in Sentry features like Session Replay. Update withSentryConfig
in your next.config.(js|mjs)
file with the following option:
next.config.mjs
export default withSentryConfig(nextConfig, {
reactComponentAnnotation: {
enabled: true,
},
});
Are you developing with Turbopack?
Let's test your setup and confirm that Sentry is working correctly and sending data to your Sentry project.
To verify that Sentry captures errors and creates issues in your Sentry project, add a test button to an existing page or create a new one:
<button
type="button"
onClick={() => {
throw new Error("Sentry Test Error");
}}
>
Break the world
</button>;
Open the page in a browser (for most Next.js applications, this will be at localhost) and click the button to trigger a frontend error.
Important
Errors triggered from within your browser's developer tools (like the browser console) are sandboxed, so they will not trigger Sentry's error monitoring.
To test tracing, create a test API route like /api/sentry-example-api
:
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// A faulty API route to test Sentry's error monitoring
export function GET() {
throw new Error("Sentry Example API Route Error");
return NextResponse.json({ data: "Testing Sentry Error..." });
}
Next, update your test button to call this route and throw an error if the response isn't ok
:
<button
type="button"
onClick={async () => {
await Sentry.startSpan({
name: 'Example Frontend Span',
op: 'test'
}, async () => {
const res = await fetch("/api/sentry-example-api");
if (!res.ok) {
throw new Error("Sentry Example Frontend Error");
}
});
}
>
Break the world
</button>;
Open the page in a browser (for most Next.js applications, this will be at localhost) and click the button to trigger two errors:
- a frontend error
- an error within the API route
Additionally, this starts a performance trace to measure the time it takes for the API request to complete.
Now, head over to your project on Sentry.io to view the collected data (it takes a couple of moments for the data to appear).
Need help locating the captured errors in your Sentry project?
At this point, you should have integrated Sentry into your Next.js application and should already be sending data to your Sentry project.
Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are:
- Instrument Next.js server actions
- Configure server-side auto-instrumentation
- Learn how to manually capture errors
- Continue to customize your configuration
- Learn more about our Vercel integration
Are you having problems setting up the SDK?
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").