Manual Setup

Learn how to set up the SDK manually.

If you can't (or prefer not to) run the automatic setup, you can follow the instructions below to configure your application.

Copied
npm install @sentry/nextjs --save

If you're updating your Sentry SDK to the latest version, check out our migration guide to learn more about breaking changes.

Use withSentryConfig to extend the default Next.js options. This will apply instrumentation to your application.

Include the following in your next.config.js or next.config.mjs:

next.config.js
Copied
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",

  // An auth token is required for uploading source maps.
  authToken: process.env.SENTRY_AUTH_TOKEN,

  silent: false, // Can be used to suppress logs
});

withSentryConfig uses a custom Webpack plugin to manage your sourcemaps and releases under the hood. If withSentryConfig does not provide the option you need to modify, you may override the sentryWebpackPluginOptions directly via unstable_sentryWebpackPluginOptions.

Create three files in the root directory of your Next.js application: sentry.client.config.js, sentry.server.config.js and sentry.edge.config.js. In these files, add your initialization code for the client-side SDK and server-side SDK, respectively. We've included some examples below.

Please note that there are slight differences between these files since they run in different places (browser, server, edge), so copy them carefully!

sentry.client.config.(js|ts)
Copied
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
});

We recommend you include your DSN directly in these three files. Alternatively you can pass the DSN via a public environment variable like NEXT_PUBLIC_SENTRY_DSN.

While the client initialization code will be injected into your application's client bundle by withSentryConfig which we set up earlier, the configuration for the server and edge runtime needs to be imported from a Next.js Instrumentation file. To set up this file, enable the Next.js instrumentation hook by setting the experimental.instrumentationHook to true in your next.config.js. Then add a instrumentation.ts file to the root directory of your Next.js application (or inside the src folder if you're using one) and add the following content:

instrumentation.(js|ts)
Copied
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");
  }
}

Make sure that the import statements point to your newly created sentry.server.config.(js|ts) and sentry.edge.config.(js|ts) files.

To capture React render errors you need to add Error components for the App Router and the Pages Router respectively.

Create a Custom Next.js Global Error component for the App router:

global-error.tsx
Copied
"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>
  );
}

Note that if you create Next.js error.js files, these files will take precedence over the global-error.js file. This means, that if you want to report errors that are caught by error.js files, you need to manually capture them:

error.tsx
Copied
"use client";

import { useEffect } from "react";
import * as Sentry from "@sentry/nextjs";

export default function ErrorPage({
  error,
}: {
  error: Error & { digest?: string };
}) {
  useEffect(() => {
    // Log the error to Sentry
    Sentry.captureException(error);
  }, [error]);

  return (
    <div>
      <h2>Something went wrong!</h2>
    </div>
  );
}

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). The onRequestError hook is a feature provided by Next.js, which allows reporting errors to Sentry.

To report errors using the onRequestError hook, pass all arguments to the captureRequestError function:

instrumentation.ts
Copied
import * as Sentry from "@sentry/nextjs";

export const onRequestError = Sentry.captureRequestError;

If you need additional logic within the onRequestError hook, call captureRequestError with all arguments passed to onRequestError:

instrumentation.ts
Copied
import * as Sentry from "@sentry/nextjs";
import type { Instrumentation } from 'next';

export const onRequestError: Instrumentation.onRequestError = (...args) => {
  Sentry.captureRequestError(...args);

  // ... additional logic here
};

Create a Custom Next.js Error Page and call captureUnderscoreErrorException in your Error Page's getInitialProps method:

_error.tsx
Copied
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:

Copied
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>
  );
}

By default, withSentryConfig will add a custom Webpack plugin to your configuration that runs for both server and client builds. This means that when you run a production build (next build), sourcemaps will be generated and uploaded to Sentry, so that you get readable stack traces in your Sentry issues.

For the SDK to be able to upload source maps to Sentry, you need to provide an auth token. You can pass an auth token directly via the authToken option:

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  // Specify the organization and project to upload source maps to
  org: "example-org",
  project: "example-project",

  // Pass the auth token
  authToken: process.env.SENTRY_AUTH_TOKEN,
});

Alternatively, you can set the SENTRY_AUTH_TOKEN environment variable:

.env
Copied
SENTRY_AUTH_TOKEN=sntrys_YOUR_TOKEN_HERE

You can disable the custom sourcemap plugin as follows:

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  sourcemaps: {
    disable: true,
  },
});

Depending on your deployment setup, adding sentry/nextjs to your app may cause your source code to be visible in browser devtools when it wasn't before. (This happens because of the default behavior of webpack's source-map built-in devtool.) To prevent this, you can use hidden-source-map rather than source-map, which will prevent your built files from containing a sourceMappingURL comment, thus making sourcemaps invisible to the browser. To use hidden-source-map, add a sentry object to nextConfig above, and set the hideSourceMaps option to true:

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  hideSourceMaps: true,
});

If you find that there are some frames in your client-side stack traces that aren't getting source-mapped even when most others are, the issue might be that those frames are from files in static/chunks/ rather than static/chunks/pages/. By default, such files aren't uploaded because the majority of the files in static/chunks/ only contain Next.js or third-party code.

To upload all of the files and source maps, including ones from third-party packages, set the widenClientFileUpload option to true:

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  widenClientFileUpload: true,
});

You might notice that Sentry events are sometimes blocked by ad blockers. Ad blockers can be circumvented by using tunneling.

The Sentry Next.js SDK provides an easy way to set up tunneling for your application. Use the tunnelRoute option to provide the SDK a route to use to tunnel events to Sentry:

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  tunnelRoute: "/monitoring-tunnel",
});

Setting this option will add an API endpoint to your application that is used to forward Sentry events to the Sentry servers.

Please note that this option will tunnel Sentry events through your Next.js application so you might experience increased server usage.

The tunnelRoute option does currently not work with self-hosted Sentry instances.

Learn more about tunneling in the troubleshooting section.

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
Copied
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/*
Copied
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 for getInitialProps
  • wrapGetServerSidePropsWithSentry for getServerSideProps
  • wrapGetStaticPropsWithSentry for getStaticProps
  • wrapErrorGetInitialPropsWithSentry for getInitialProps in custom Error pages
  • wrapAppGetInitialPropsWithSentry for getInitialProps in custom App components
  • wrapDocumentGetInitialPropsWithSentry for getInitialProps in custom Document components

If you want auto-instrumentation to apply by default, but want to exclude certain routes, use the excludeServerRoutes option:

next.config.mjs
Copied
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
Copied
export default withSentryConfig(nextConfig, {
  autoInstrumentMiddleware: false,
});

You can set the automaticVercelMonitors option to automatically create Cron Monitors in Sentry if you have configured Vercel Cron Jobs.

Automatic instrumentation of Vercel cron jobs currently only works for the Pages Router. App Router route handlers are not yet supported.

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  automaticVercelMonitors: true,
});

If you want the Sentry SDK to be available in your server-side & 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.

Set the disableLogger option to true to strip the Sentry SDK debug logger out of your client bundles, saving bundle size. Please note that this will effectively override and disable the debug option in your Sentry.init() calls.

next.config.mjs
Copied
export default withSentryConfig(nextConfig, {
  disableLogger: true,
});
Help improve this content
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").