Hirefullstack – Software Engineering & IT-Beratung aus Berlin
← Zur Übersicht
Kern 11 Min Lesezeit

Fehler- und Ladezustände

Was passiert, wenn etwas schiefgeht – und wer es auffängt

In einem Satz

error.tsx fängt Fehler eines Bereichs ab, not-found.tsx die fehlenden Adressen. Beides sind Dateien, keine Konfiguration.

Ohne Auffangnetz bedeutet ein Fehler beim Datenladen: weiße Seite. Next.js bringt dafür zwei Dateien mit, die genau wie loading.tsx einfach im Ordner liegen.

error.tsx

app/blog/error.tsx
"use client";      // Pflicht – error.tsx ist immer eine Client-Komponente

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>Da ist etwas schiefgegangen.</h2>
      <button onClick={reset}>Nochmal versuchen</button>
    </div>
  );
}
reset() baut den fehlgeschlagenen Bereich neu auf – ohne die ganze Seite neu zu laden.

Die Datei error.tsxFängt Fehler aus dem Bereich darunter ab und zeigt stattdessen etwas Lesbares. Muss eine Client-Komponente sein. fängt alles ab, was in ihrem Ordner und darunter beim Rendern schiefgeht. Der Rest der Seite – Layout, Kopfzeile, Navigation – bleibt stehen und bedienbar.

Stolperstein Das eigene Layout fängt sie nicht

app/blog/error.tsx fängt Fehler aus app/blog/page.tsx ab – aber nicht aus app/blog/layout.tsx. Dafür ist die Ebene darüber zuständig. Wer ein Layout absichern will, braucht das error.tsx eine Stufe höher.

Achtung In Produktion siehst du die Fehlermeldung nicht

Next.js ersetzt sie durch eine allgemeine Meldung plus eine digest-Kennung, damit nichts Internes nach außen dringt. Über diese Kennung findest du den echten Fehler im Serverprotokoll wieder.

not-found.tsx

app/blog/[slug]/page.tsx
import { notFound } from "next/navigation";

export default async function Seite({ params }) {
  const { slug } = await params;
  const artikel = await ladeArtikel(slug);

  if (!artikel) notFound();     // hält hier an und zeigt not-found.tsx

  return <article>{artikel.inhalt}</article>;
}

not-found.tsxWird gezeigt, wenn eine Adresse nicht existiert oder der Code `notFound()` aufruft. greift in zwei Fällen: wenn du notFound() aufrufst, und wenn eine Adresse gar nicht existiert. Beides liefert korrekt den Statuscode 404 – wichtig, damit Suchmaschinen die Seite nicht indexieren.

Fehlender Datensatz
sieht aus wie ein Fehler
const artikel = await ladeArtikel(slug);
if (!artikel) throw new Error("Artikel nicht gefunden");
ist eine 404
const artikel = await ladeArtikel(slug);
if (!artikel) notFound();

„Gibt es nicht“ ist kein Fehler, sondern ein Ergebnis. Mit throw bekämst du eine 500 und die Fehlerseite – für Suchmaschinen und Nutzer das falsche Signal.

Die Ebenen im Überblick

ebenen.txt
app/
  error.tsx              fängt alles, auch Fehler aus app/blog/layout.tsx
  global-error.tsx       letzter Notnagel, ersetzt auch das Wurzel-Layout
  not-found.tsx          404 für die ganze Anwendung
  blog/
    error.tsx            fängt Fehler aus blog/page.tsx und darunter
    loading.tsx          Platzhalter während des Ladens
    page.tsx
Gut zu wissen global-error.tsx braucht eigenes html und body

Weil es das Wurzel-Layout ersetzt, muss es die HTML-Hülle selbst mitbringen. Es greift nur, wenn schon das Wurzel-Layout scheitert – in der Praxis selten, aber der Unterschied erklärt die ungewöhnliche Anforderung.

Erwartete und unerwartete Fehler

Nimm es, wenn …
  • +

    notFound() für „gibt es nicht“

  • +

    Rückgabewerte für Validierungsfehler – etwa aus einer Server Action

  • +

    error.tsx für das Unerwartete: Datenbank weg, fremde API antwortet nicht

Lass es, wenn …
  • throw für alles, was du eigentlich erwartest

  • Fehlerdetails im Browser anzeigen

  • Auf error.tsx verzichten und hoffen

Genauer erklärt: Was error.tsx nicht abfängt optional
grenzen.txt
error.tsx fängt:
  ✓ Fehler beim Rendern der Seite und darunter
  ✓ Fehler beim Datenladen in diesen Komponenten

error.tsx fängt NICHT:
  ✗ Fehler im eigenen Layout   → Ebene darüber zuständig
  ✗ Fehler in Event-Handlern   → try/catch im Handler
  ✗ Fehler in Server Actions   → Rückgabewert statt throw
  ✗ Fehler nach dem Rendern    → z. B. in einem setTimeout

Für Server Actions ist der Rückgabewert der bessere Weg: return { fehler: "…" } statt throw. So kannst du die Meldung im Formular anzeigen, ohne die ganze Ansicht durch die Fehlerseite zu ersetzen.

Sitzt das schon?

4 Fragen zu dieser Lektion. Falsche Antworten landen in deiner Statistik.

Jetzt selbst schreiben

Fehleranzeige mit Wiederholen

Baue die Anzeige, die Next.js bei einem Fehler einblendet. Sie zeigt eine allgemeine Meldung und einen Knopf, der den Bereich neu aufbaut. (In Next.js bekäme die Komponente error und reset von außen; hier reichst du reset selbst herein, damit es prüfbar ist.)

  • Die Überschrift Da ist etwas schiefgegangen. erscheint
  • Die technische Fehlermeldung wird nicht angezeigt
  • Ein Klick auf Nochmal versuchen ruft reset auf
import { useState } from "react";

type Props = {
  error: Error & { digest?: string };
  reset: () => void;
};

// In Next.js: "use client" + Datei heißt error.tsx
export function Fehleranzeige({ error, reset }: Props) {
  // TODO: allgemeine Meldung + Knopf, der reset aufruft
  return <div>???</div>;
}

export default function App() {
  const [versuche, setVersuche] = useState(0);
  const fehler = Object.assign(new Error("DB_CONN_REFUSED bei 10.0.0.7"), {
    digest: "a1b2c3",
  });

  return (
    <div style={{ fontFamily: "system-ui", padding: 16 }}>
      <p data-testid="versuche">Versuche: {versuche}</p>
      <Fehleranzeige error={fehler} reset={() => setVersuche((v) => v + 1)} />
    </div>
  );
}

Hirefullstack

Ihr braucht React-Verstärkung im Team?

Wir bauen seit Jahren React- und Next.js-Anwendungen für Kunden in ganz Deutschland – als einzelner Experte, als Verstärkung fürs Bestandsteam oder als komplettes Scrum-Team.

Projekt besprechen →