Manual Setup

Learn how to manually set up Sentry in your Next.js app and capture your first errors.

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:

Copied
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
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",

  // 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:

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

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

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

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

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
Copied
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
Copied
SENTRY_AUTH_TOKEN=sntrys_YOUR_TOKEN_HERE

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

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

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
Copied
export default withSentryConfig(nextConfig, {
  automaticVercelMonitors: true,
});

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
Copied
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:

Copied
<button
  type="button"
  onClick={() => {
    throw new Error("Sentry Test Error");
  }}
>
  Break the world
</button>;

To test tracing, create a test API route like /api/sentry-example-api:

Copied
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:

Copied
<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:

Are you having problems setting up the SDK?
Was this helpful?
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").