Fehler-Monitoring für Next.js.

Mit @sentry/nextjs erfasst Fehlo Fehler aus dem Browser, aus Server Components, Route Handlers und Middleware. Die Einrichtung von Hand dauert fünf Dateien.

Stand: 21.10.2026, @sentry/nextjs 11.8.0, Next.js 14 bis 16 mit App Router.

1. Paket installieren

Terminal
npm install @sentry/nextjs

Der Assistent npx @sentry/wizard -i nextjs meldet sich am Zielserver an; den haben wir mit Fehlo nicht getestet. Die Einrichtung von Hand braucht fünf Dateien, alle im Projektordner oder in src/.

2. Browser

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

Sentry.init({
  dsn: "https://<key>@app.fehlo.de/<project-id>",
  dataCollection: {
    userInfo: false,
  },
});

export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;

Der Export onRouterTransitionStart misst Seitenwechsel im Browser.

3. Server und Edge

Dieselbe Konfiguration für die Node.js- und die Edge-Laufzeit:

sentry.server.config.ts
import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: "https://<key>@app.fehlo.de/<project-id>",
  dataCollection: {
    userInfo: false,
  },
});
sentry.edge.config.ts
import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: "https://<key>@app.fehlo.de/<project-id>",
  dataCollection: {
    userInfo: false,
  },
});

Next.js lädt sie über instrumentation.ts. onRequestError meldet Fehler aus Server Components, Route Handlers und Middleware.

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

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

export const onRequestError = Sentry.captureRequestError;

4. Fehler beim Rendern

Fehler, die das Rendern der ganzen App abbrechen, fängt app/global-error.tsx:

app/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 statusCode={0} />
      </body>
    </html>
  );
}

5. Build und Source Maps

withSentryConfig lädt beim Build die Source Maps hoch. Seit Version 11 importierst du es aus @sentry/nextjs/config. Die Option sentryUrl zeigt auf Fehlo statt auf sentry.io.

next.config.ts
import type { NextConfig } from "next";
import { withSentryConfig } from "@sentry/nextjs/config";

const nextConfig: NextConfig = {};

export default withSentryConfig(nextConfig, {
  sentryUrl: "https://app.fehlo.de/",
  org: "<organisation-slug>",
  project: "<project-slug>",
  authToken: process.env.SENTRY_AUTH_TOKEN,
  silent: !process.env.CI,
  widenClientFileUpload: true,
});

Das Token legst du in Fehlo unter Einstellungen, API-Tokens an, mit der Vorlage „Für Source Maps“. Organisation und Projekt stehen in der Adresszeile der Projekteinstellungen: /<organisation>/settings/projects/<projekt>. Setz das Token im CI als SENTRY_AUTH_TOKEN, nicht im Code.

6. Testen

Leg eine Seite mit einem Knopf an, der einen Fehler wirft, und öffne sie im Browser:

app/fehlo-test/page.tsx
"use client";

export default function FehloTest() {
  return (
    <button type="button" onClick={() => { throw new Error("Fehlo test error"); }}>
      Test error
    </button>
  );
}

Performance messen

Ergänze in allen drei Sentry.init-Aufrufen tracesSampleRate: 0.2,. Transaktionen zählen bei Fehlo zu einem eigenen Kontingent, nicht zu den Ereignissen.

Häufige Fragen

Es kommt nichts an. Was prüfe ich?

Erstens den DSN: Er muss auf app.fehlo.de zeigen. Zweitens, ob dein Server oder Browser https://app.fehlo.de erreicht (Firewall, Proxy, Werbeblocker). Drittens, ob dein Kontingent für den Monat aufgebraucht ist; dann bekommst du eine Mail. Viertens, ob sampleRate oder beforeSend Ereignisse verwirft. Fehlen nur Performance-Daten, sind vielleicht die Transaktionen des Monats aufgebraucht.