The full NextJS Setup Guide For Error Reporting to Sentry

Sentry is a real-time error tracking and performance monitoring tool that helps developers identify, diagnose, and fix issues in their applications quickly. It supports various languages and frameworks, providing detailed insights into errors, stack traces, and user impact. The benefits of using Sentry include faster debugging, improved app reliability, and enhanced user experience through proactive issue resolution. With features like alerting, contextual data, and performance tracing, Sentry empowers teams to maintain high-quality code and reduce downtime.

This guide will show you how to fully set up a Next.js project using the App Router (not the Pages Router), with the ability to report errors to Sentry. It covers both server and client components. If you're only using one or the other, feel free to cherry-pick the relevant sections.

Before continuing, we highly recommend reviewing the following:

  • Reliable Error Tracking
  • Next.js Instrumentation Pattern

Requirements

  • Reliable Error Tracking set up
  • Next.js Instrumentation Pattern applied
  • A Sentry account and a valid DSN for your project
  • Familiarity with the Sentry dashboard

Environment Variables

  • NEXT_PUBLIC_SENTRY_DSN: Sentry DSN for sending error reports
  • NEXT_PUBLIC_NODE_ENV: Defines the current environment
  • NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE: Controls performance sample rate

Project Folder Structure

Ensure your project matches the following structure:

root
├── .env.local
├── next.config.js
├── tsconfig.json
├── package.json
├── package-lock.json
└── src
    ├── app
    ├── components
    ├── config
    ├── hooks
    ├── instrumentation
    ├── styles
    ├── utils
    └── instrumentation.ts

Install Sentry Packages

npm install --save @sentry/nextjs@^8.25.0

Convert next.config.js to next.config.mjs

This helps you take advantage of modern ESM features, which Sentry supports:

// next.config.mjs

import { withSentryConfig } from '@sentry/nextjs'

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  experimental: {
    instrumentationHook: true
  },
  webpack: { devtool: 'source-map' },
  pageExtensions: ['js', 'jsx', 'ts', 'tsx']
}

export default withSentryConfig(
  nextConfig,
  {
    silent: true,
    org: process.env.SENTRY_ORG,
    project: process.env.SENTRY_PROJECT
  },
  {
    disableServerWebpackPlugin: true,
    disableClientWebpackPlugin: true,
    widenClientFileUpload: true,
    transpileClientSDK: true,
    hideSourceMaps: true,
    disableLogger: true,
    automaticVercelMonitors: true
  }
)

Add Source Map Command

// package.json

"scripts": {
  "sentry:sourcemaps": "sentry-cli sourcemaps inject --org YOUR_ORGANIZATION_HERE --project YOUR_PROJECT_NAME_HERE ./.next && sentry-cli sourcemaps upload --org YOUR_ORGANIZATION_HERE --project YOUR_PROJECT_NAME_HERE ./.next"
}

Update Project Structure with Sentry Folder

src
├── sentry
│   ├── sentry.client.config.ts
│   ├── sentry.edge.config.ts
│   └── sentry.server.config.ts

Update tsconfig.json:

"paths": {
  "@sentry/*": ["./src/sentry/*"]
}

Sentry Configs

sentry.edge.config.ts

// src/sentry/sentry.edge.config.ts

import * as Sentry from '@sentry/nextjs'

const edgeSentryInstance = Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  enabled: true,
  environment: process.env.NEXT_PUBLIC_NODE_ENV,
  tracesSampleRate:
    process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE
      ? parseFloat(process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE)
      : 0.3,
  debug: false
})

export default edgeSentryInstance

sentry.server.config.ts

// src/sentry/sentry.server.config.ts

import * as Sentry from '@sentry/nextjs'

const serverSentryInstance = Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  enabled: true,
  environment: process.env.NEXT_PUBLIC_NODE_ENV,
  tracesSampleRate:
    process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE
      ? parseFloat(process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE)
      : 0.3,
  debug: false
  // spotlight: process.env.NODE_ENV === 'development',
})

export default serverSentryInstance

sentry.client.config.ts

// src/sentry/sentry.client.config.ts

import * as Sentry from '@sentry/nextjs'

const clientSentryInstance = Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  enabled: true,
  environment: process.env.NEXT_PUBLIC_NODE_ENV,
  tracesSampleRate:
    process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE
      ? parseFloat(process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE)
      : 0.3,
  debug: false,
  replaysOnErrorSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  integrations: [
    ...(typeof window !== 'undefined'
      ? [
          Sentry.replayIntegration({
            maskAllText: false,
            blockAllMedia: false
          })
        ]
      : [])
  ]
})

export default clientSentryInstance

Register Sentry in instrumentation.ts

// src/instrumentation.ts

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./sentry/sentry.server.config')
  }

  if (process.env.NEXT_RUNTIME === 'edge') {
    await import('./sentry/sentry.edge.config')
  }
}

Update ErrorTracer to Capture Errors

// src/components/error-tracer.tsx

'use client'

import clientSentryInstance from '@sentry/sentry.client.config'
import { useEffect } from 'react'

export default function ErrorTracer() {
  useEffect(() => {
    const handleError = (event: ErrorEvent) => {
      clientSentryInstance?.captureException(event.error)
    }

    const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
      clientSentryInstance?.captureException(event.reason)
    }

    window.addEventListener('error', handleError)
    window.addEventListener('unhandledrejection', handleUnhandledRejection)

    return () => {
      window.removeEventListener('error', handleError)
      window.removeEventListener('unhandledrejection', handleUnhandledRejection)
    }
  }, [])

  return null
}

Validate

Refer back to Reliable Error Tracking and test with a button click error.

Enable debug mode in Sentry config and you should see:

  • 📦 Terminal log showing Sentry initialized
  • ✅ Sentry dashboard showing exact file and line number
  • 🎥 Session replay of user actions before the crash
  • 📎 Terminal during build showing source maps uploaded

Conclusion

Setting up Sentry for a Next.js App Router project gives you complete visibility into client and server errors, performance bottlenecks, and user behavior. This integration ensures faster debugging, better user experiences, and more stable production deployments.

Check our GitHub repo under the nextjs-error-reporting-setup-sentry folder for reference.

Written by

Engineering Team

Engineering Team

Development

Our engineering team is a group of highly skilled and experienced software engineers with a passion for building high-quality web and mobile applications. They are dedicated to creating reliable, scalable, and user-friendly software solutions that meet the needs of our clients.

Tap a star to rate

More posts

The full NextJS Setup Guide For Error Reporting to Signoz

The full NextJS Setup Guide For Error Reporting to Signoz

The full guide for setting up SigNoz for NextJS server side and browser side to report errors

Apr 9, 2025
How to organize instrumentation for NextJS

How to organize instrumentation for NextJS

How to structure and organize your instrumentation logic in a Next.js project

Apr 8, 2025