Skip to content

Fix: Sentry Not Working — Errors Not Captured, Source Maps Missing, or Performance Traces Empty

FixDevs ·

Quick Answer

How to fix Sentry issues — SDK initialization, source map uploads, error boundaries, performance monitoring, Next.js integration, release tracking, and alert configuration.

The Problem

Errors throw in your app but nothing appears in Sentry:

throw new Error('Something went wrong');
// Error fires but Sentry dashboard shows zero events

Or errors appear but stack traces show minified code:

TypeError: Cannot read properties of undefined
  at e.render (main.abc123.js:1:45678)
  at t.processChild (main.abc123.js:1:12345)

Or performance monitoring is enabled but no traces appear:

Sentry.init({
  tracesSampleRate: 1.0,
});
// Zero transactions in the Performance tab

Why This Happens

Sentry captures errors and performance data through its SDK, which must be correctly initialized and configured:

  • Sentry.init() must run before any errors occur — the SDK intercepts uncaught exceptions and unhandled promise rejections. If initialization happens after the first error, that error is lost. In Next.js, the SDK must be initialized in multiple places (client, server, edge).
  • Source maps must be uploaded to Sentry — production builds are minified. Without source maps, Sentry can’t map minified code back to your original source. Source maps must be uploaded during the build process, not at runtime.
  • The DSN must be correct — the Data Source Name tells the SDK where to send events. A wrong DSN silently drops all events. The DSN is project-specific and found in Sentry’s project settings.
  • Sample rates control what’s capturedtracesSampleRate: 0 means no performance traces are collected. In production, you typically sample a percentage (e.g., 0.1 for 10%) to reduce costs.

Fix 1: Next.js Integration

npx @sentry/wizard@latest -i nextjs
# Or manually:
npm install @sentry/nextjs
// sentry.client.config.ts — client-side SDK
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,

  // Performance monitoring
  tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,

  // Session replay (optional)
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    Sentry.replayIntegration(),
    Sentry.browserTracingIntegration(),
  ],

  // Filter noisy errors
  ignoreErrors: [
    'ResizeObserver loop',
    'Non-Error promise rejection',
    /Loading chunk \d+ failed/,
  ],

  // Before sending — sanitize sensitive data
  beforeSend(event) {
    if (event.request?.cookies) {
      delete event.request.cookies;
    }
    return event;
  },
});
// sentry.server.config.ts — server-side SDK
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
});
// sentry.edge.config.ts — edge runtime SDK
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  tracesSampleRate: 0.1,
});
// next.config.mjs — wrap with Sentry
import { withSentryConfig } from '@sentry/nextjs';

const nextConfig = {};

export default withSentryConfig(nextConfig, {
  org: 'my-org',
  project: 'my-project',
  authToken: process.env.SENTRY_AUTH_TOKEN,

  // Upload source maps
  sourcemaps: {
    deleteSourcemapsAfterUpload: true,  // Don't expose source maps publicly
  },

  // Automatically instrument API routes
  autoInstrumentServerFunctions: true,
  autoInstrumentMiddleware: true,
  autoInstrumentAppRouter: true,

  // Hide source maps from the client
  hideSourceMaps: true,

  // Silence warnings during build
  silent: !process.env.CI,
});

Fix 2: Manual Error Capture

// Capture exceptions explicitly
import * as Sentry from '@sentry/nextjs';

async function fetchData() {
  try {
    const res = await fetch('/api/data');
    if (!res.ok) throw new Error(`API error: ${res.status}`);
    return res.json();
  } catch (error) {
    // Capture with additional context
    Sentry.captureException(error, {
      tags: { section: 'data-fetch' },
      extra: { url: '/api/data' },
      level: 'error',
    });
    throw error;
  }
}

// Capture messages (non-error events)
Sentry.captureMessage('User reached rate limit', {
  level: 'warning',
  tags: { userId: 'user-123' },
});

// Set user context — appears on all subsequent events
Sentry.setUser({
  id: user.id,
  email: user.email,
  username: user.name,
});

// Clear on logout
Sentry.setUser(null);

// Add breadcrumbs — trail of events leading to an error
Sentry.addBreadcrumb({
  category: 'navigation',
  message: 'User navigated to /dashboard',
  level: 'info',
});

Sentry.addBreadcrumb({
  category: 'api',
  message: 'Fetched user profile',
  data: { userId: '123', status: 200 },
  level: 'info',
});

Fix 3: React Error Boundary

// app/global-error.tsx — Next.js App Router global error boundary
'use client';

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

export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    Sentry.captureException(error);
  }, [error]);

  return (
    <html>
      <body>
        <div style={{ padding: '2rem', textAlign: 'center' }}>
          <h2>Something went wrong!</h2>
          <p>Our team has been notified.</p>
          <button onClick={reset}>Try again</button>
        </div>
      </body>
    </html>
  );
}

// app/dashboard/error.tsx — route-specific error boundary
'use client';

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

export default function DashboardError({
  error,
  reset,
}: {
  error: Error;
  reset: () => void;
}) {
  useEffect(() => {
    Sentry.captureException(error, {
      tags: { page: 'dashboard' },
    });
  }, [error]);

  return (
    <div>
      <h2>Dashboard Error</h2>
      <p>{error.message}</p>
      <button onClick={reset}>Retry</button>
    </div>
  );
}

Fix 4: Source Map Configuration

# .env
SENTRY_AUTH_TOKEN=sntrys_xxxxxxxx  # From Settings → Auth Tokens
SENTRY_ORG=my-org
SENTRY_PROJECT=my-nextjs-app
NEXT_PUBLIC_SENTRY_DSN=https://[email protected]/zzz
// For non-Next.js projects — upload source maps manually
// Install: npm install -D @sentry/cli

// .sentryclirc
[auth]
token=sntrys_xxxxxxxx

[defaults]
org=my-org
project=my-project
# Upload source maps after build
npx sentry-cli sourcemaps upload \
  --release=1.0.0 \
  --url-prefix='~/' \
  ./dist

# Or in package.json
# "postbuild": "sentry-cli sourcemaps upload --release=$(git rev-parse HEAD) ./dist"

Fix 5: Performance Monitoring

// Custom transactions
import * as Sentry from '@sentry/nextjs';

async function processOrder(orderId: string) {
  return Sentry.startSpan(
    { name: 'process-order', op: 'task' },
    async (span) => {
      // Child spans for sub-operations
      const order = await Sentry.startSpan(
        { name: 'fetch-order', op: 'db.query' },
        () => db.query.orders.findFirst({ where: eq(orders.id, orderId) }),
      );

      await Sentry.startSpan(
        { name: 'charge-payment', op: 'http.client' },
        () => chargePayment(order),
      );

      await Sentry.startSpan(
        { name: 'send-email', op: 'http.client' },
        () => sendConfirmation(order),
      );

      span.setAttributes({ orderId, total: order.total });
      return order;
    },
  );
}

// API route instrumentation — automatic with withSentryConfig
// app/api/users/route.ts
export async function GET() {
  // Sentry automatically traces this route
  const users = await db.query.users.findMany();
  return Response.json(users);
}

Fix 6: Alerts and Issue Management

// Sentry.init — configure which errors trigger alerts
Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,

  // Attach release version for tracking
  release: process.env.NEXT_PUBLIC_SENTRY_RELEASE || 'development',

  // Environment for filtering
  environment: process.env.NODE_ENV,

  // Before sending — filter or modify events
  beforeSend(event, hint) {
    const error = hint.originalException;

    // Ignore specific errors
    if (error instanceof TypeError && error.message.includes('cancelled')) {
      return null;  // Don't send this event
    }

    // Add custom fingerprint for grouping
    if (error instanceof ApiError) {
      event.fingerprint = ['api-error', error.endpoint, String(error.status)];
    }

    return event;
  },

  // Before sending breadcrumbs — filter sensitive data
  beforeBreadcrumb(breadcrumb) {
    if (breadcrumb.category === 'xhr' && breadcrumb.data?.url?.includes('/api/auth')) {
      breadcrumb.data = { ...breadcrumb.data, body: '[REDACTED]' };
    }
    return breadcrumb;
  },
});

Still Not Working?

Zero events in Sentry — check the DSN is correct in NEXT_PUBLIC_SENTRY_DSN. Open browser DevTools → Network and filter for sentry or ingest — you should see outgoing requests when errors occur. If requests appear but return 4xx, the DSN is wrong or the project is disabled.

Events captured but stack traces are minified — source maps aren’t uploaded. Verify SENTRY_AUTH_TOKEN is set during build (not just at runtime). Check the Sentry dashboard → Settings → Source Maps to see if maps were uploaded for the current release. The release in Sentry.init() must match the release used during upload.

Performance tab is emptytracesSampleRate might be 0. Set it to 1.0 in development to capture all traces. Also check that browserTracingIntegration() is in the integrations array for client-side tracing.

Too many events / hitting quota — use beforeSend to filter noisy errors, ignoreErrors for known non-actionable errors, and lower tracesSampleRate in production. Set sampleRate: 0.5 to send only 50% of error events (not recommended for critical apps).

For related monitoring issues, see Fix: OpenTelemetry Not Working and Fix: Next.js App Router Not Working.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles