Mein Platz in der WordPress-Community
- Mein wordpress.org-Konto besteht seit 2006.
- Ich habe zum WordPress-Core in den Versionen 7.0 und 7.1 beigetragen.
- Ich betreue 30 Plugins auf wordpress.org.
- Ich organisiere WordCamps und trete dort als Speaker auf.
- Ich war bei jedem WordCamp Europe von 2017 bis 2026 dabei.
Mariusz Szatkowski hier: Ich entwickle allein von Gdynia aus und arbeite seit 2006 mit WordPress. Für Essen schreibe ich hier über den Teil einer Next.js-Anwendung, der erst auffällt, wenn etwas schiefgeht: Fehlerseiten, Logs und Alarme. Alle Angaben zu Next.js stammen aus der Dokumentation auf nextjs.org, Stand der Seiten Oktober und November 2026. Die Codebeispiele zu Fehlerseite und onRequestError habe ich mit Version 16.4.6 gebaut und laufen lassen, die laut npm-Registry am 9. November 2026 erschien.
Welche Dateien fangen welchen Fehler?
Die Dokumentation trennt zwei Fehlerarten. Erwartete Fehler gehören zum normalen Betrieb, etwa eine fehlgeschlagene Validierung oder ein Request, der nicht klappt. Sie sollen als Rückgabewert modelliert werden, nicht als geworfene Exception. Alles andere sind unerwartete Ausnahmen. Die wirft man, und eine Error Boundary fängt sie.
| Datei | Fängt | Wichtig |
|---|---|---|
error.js | Fehler im Segment und darunter | umschließt loading.js, not-found.js, page.js und verschachtelte Layouts, aber nicht layout.js oder template.js im selben Segment |
global-error.js | Fehler im Root-Layout | ersetzt das Layout, braucht eigene html- und body-Tags, kein metadata-Export |
not-found.js | notFound() im Segment | die Datei im Root fängt auch alle URLs, die zu keiner Route passen |
global-not-found.js | URLs ohne passende Route | laut Dokumentation experimentell, Schalter experimental.globalNotFound |
catchError | einzelne Komponenten | Boundary unabhängig von Routensegmenten |
Zwei Grenzen stehen ausdrücklich in der Referenz zu error.js. Fehler in Event-Handlern und in asynchronem Code fängt keine Boundary, weil sie nach dem Rendern laufen. Dort fängt man selbst und legt den Fehler in den State. Und global-error.js rendert ohne Ihre globalen Styles, deshalb muss die Seite ihr eigenes Aussehen mitbringen. Seit Version 16.3.0 ist die Prop retry stabil, sie holt und rendert die Kinder der Boundary neu. reset löscht nur den Fehlerzustand und rendert ohne neuen Abruf.
Eine Fehlerseite in dieser Form genügt als Grundgerüst:
// app/dashboard/error.tsx
'use client'
export default function Error({
error,
retry,
}: {
error: unknown
retry: () => void
}) {
const digest =
error instanceof Error && 'digest' in error ? String(error.digest) : undefined
return (
<div role="alert">
<h2>Das hat leider nicht geklappt.</h2>
{digest && <p>Fehlernummer: {digest}</p>}
<button onClick={() => retry()}>Erneut versuchen</button>
</div>
)
}Der Typ unknown stammt aus der Dokumentation: Ein Fehler aus einer Client Component kommt unverändert an und muss nicht einmal ein Error sein, deshalb die Prüfung vor dem Zugriff auf digest.
Warum der Browser nur eine Nummer sieht
Im Produktivbetrieb bekommt der Browser bei Fehlern aus Server Components laut Dokumentation eine allgemeine Meldung mit einer Kennung. Das soll verhindern, dass sensible Details nach außen gelangen. Die Kennung heißt error.digest, ist ein automatisch erzeugter Hash des Fehlers und passt zum Eintrag im Server-Log. In meinem Testaufbau stand dieselbe Nummer im Next.js-Log, in der Antwort an den Browser und in der Zeile, die onRequestError schrieb.
Daraus folgt ein praktischer Ablauf, den ich für Anwendungen mit Kundenkontakt vorschlage: Die Fehlerseite zeigt die Nummer an, Ihr Support bekommt sie genannt und findet den Fall im Log, ohne die Person nach Details zu fragen. Das Muster kommt ohne personenbezogene Angaben aus.
Was bei 404 und 200 wirklich passiert
Hier liegt die häufigste Fehlannahme im Monitoring. Laut Dokumentation zu loading.js beginnen gestreamte Seitenantworten mit Status 200, und die ersten Header legen den Status für den Rest der Antwort fest. Zu not-found.js steht: Vor dem Streamstart liefert Next.js einen 404. Nach dem Streamstart bleibt der Status 200, und die Not-Found-Oberfläche erscheint trotzdem. In beiden Fällen setzt Next.js ein <meta name="robots" content="noindex" />. Manche Crawler führen solche Antworten als Soft-404.
Das gilt auch für Fehler. In meinem Testaufbau lieferte eine Seite, die ohne Suspense-Grenze beim Rendern abbrach, Status 500. Eine zweite Seite mit Suspense-Grenze, deren Fehler erst nach dem ersten Byte auftrat, lieferte Status 200, und onRequestError meldete den Fehler trotzdem. Das Ergebnis für den Betrieb: Ein Alarm, der nur auf 5xx wartet, übersieht einen Teil der Fehler. Wer den Statuscode für Compliance oder Analytics braucht, prüft laut Dokumentation vor dem Streamstart, etwa im Proxy, und gibt dort 404, 403 oder 401 zurück.

Foto: Anil Öztas, CC BY-SA 4.0, Wikimedia Commons.
instrumentation.ts: wo Server-Fehler zusammenlaufen
Die Referenz zu instrumentation.js beschreibt zwei Exporte. register läuft einmal pro neuer Serverinstanz und muss fertig sein, bevor der Server Anfragen annimmt. onRequestError meldet Serverfehler an einen Anbieter Ihrer Wahl, seit Version 15.0.0. Die Datei liegt im Projektstamm oder, falls vorhanden, in src.
Die Funktion bekommt drei Argumente. context sagt, wo es geknallt hat: routePath, routeType (render, route, action oder proxy), renderSource und routerKind. Zwei Hinweise der Dokumentation sind wichtig. Asynchrone Arbeit in der Funktion muss mit await abgewartet werden. Und die error-Instanz muss nicht die ursprünglich geworfene sein, weil React sie beim Rendern von Server Components verändern kann. Dann hilft digest.
Das Beispiel der Dokumentation schickt request und context komplett an einen Endpunkt. Das ist der Punkt, an dem ich bei Projekten bremse. In meinem Test enthielt request.path den Query-String (/boom?email=a%40b.de) und request.headers unter anderem cookie und x-forwarded-for. Die Fehlermeldung, die im Test eine E-Mail-Adresse nannte, stand auch in der Konsolenausgabe von Next.js selbst. Wer das Beispiel unverändert übernimmt, schickt Cookies an einen Dritten. Stattdessen baue ich die Zeile aus einer Positivliste:
// instrumentation.ts
import type { Instrumentation } from 'next'
export const onRequestError: Instrumentation.onRequestError = async (
err,
request,
context
) => {
const digest =
typeof err === 'object' && err !== null && 'digest' in err
? String(err.digest)
: undefined
console.error(
JSON.stringify({
level: 'error',
digest,
errorName: err instanceof Error ? err.name : typeof err,
route: context.routePath,
routeType: context.routeType,
method: request.method,
path: request.path.split('?')[0],
})
)
}Die Zeile enthält Nummer, Fehlertyp, Route, Kontext, Methode und den Pfad ohne Query. Die Meldung des Fehlers fehlt mit Absicht, ebenso die Header. Ob Sie einzelne Routen doch mit Meldung brauchen, klären wir schriftlich, zusammen mit einer Frist für die Löschung. Dazu gleich mehr.
OpenTelemetry: was Next.js mitbringt
Die Anleitung zu OpenTelemetry empfiehlt OpenTelemetry für die Instrumentierung und sagt, Next.js sei bereits selbst instrumentiert. Es gibt zwei Wege. @vercel/otel ist die kurze Variante: registerOTel({ serviceName: 'next-app' }) in register. Es läuft laut Dokumentation auf Vercel und bei Selbstbetrieb mit einem OpenTelemetry Collector. Die manuelle Variante nutzt NodeSDK aus einer eigenen Datei instrumentation.node.ts, die nur bei process.env.NEXT_RUNTIME === 'nodejs' geladen wird, weil NodeSDK nicht in der Edge-Runtime läuft. Wer die Edge-Runtime braucht, muss @vercel/otel nehmen.
Für den Datenschutz sind drei Details der Seite relevant:
- Der Wurzel-Span jeder Anfrage heißt
[http.method] [next.route]und trägt unter anderemhttp.routeundhttp.target. Ob dort Query-Strings landen, prüfe ich im Collector, bevor Daten den Server verlassen. - Der Span für
fetch-Aufrufe führthttp.url. Steckt in einer Backend-URL eine Kundennummer, steht sie im Trace. Der Span lässt sich mitNEXT_OTEL_FETCH_DISABLED=1abschalten, falls eine eigene fetch-Instrumentierung übernimmt. - Mit
NEXT_OTEL_VERBOSE=1erzeugt Next.js mehr Spans als üblich. Das ist für die Fehlersuche gedacht, nicht als Dauerzustand.
Eigene Spans legt man mit der OpenTelemetry-API an. Die Seite warnt, dass Spans innerhalb von register oder vor dem Start des Tracer-Providers nicht zur Anfrage gehören. Ein Span gehört dorthin, wo die Anfrage verarbeitet wird, also in die Seite, den Route Handler oder die Server Action.
Was ins Log gehört und was nicht
Das Standard-Datenschutzmodell, das die LDI NRW auf ihrer Seite vorstellt, hat einen eigenen Baustein 43 zum Protokollieren. Die aktuelle Fassung 2.0 gilt laut Seite des Landesbeauftragten Mecklenburg-Vorpommern seit dem 1. Juni 2026. Der Baustein sagt im Kern: Für Protokolle gelten die Grundsätze aus Art. 5 DS-GVO. Im Regelfall soll man auf Personen- und Inhaltsdaten im Protokollbestand verzichten, und wo der Personenbezug nötig ist, muss das begründet sein. Für Bestände mit personenbezogenen Daten müssen Löschfristen festgelegt sein. Zeitstempel sollen verlässlich und standardisiert sein, damit sich Abläufe über mehrere Systeme nachvollziehen lassen.
Daraus entsteht für eine Next.js-Anwendung diese Aufteilung:
| Feld | Ins Log? | Begründung |
|---|---|---|
digest, Fehlertyp, routePath, routeType | ja | technisch, ohne Personenbezug |
| Methode, Pfad ohne Query | ja | reicht, um die Route zu finden |
| Zeitstempel im einheitlichen Format, Release-Kennung aus Ihrer CI | ja | verknüpft Fehler mit Version und Systemen |
| Query-String | nein | kann E-Mail-Adressen, Token, Suchbegriffe enthalten |
cookie, authorization | nein | Sitzungsdaten gehören in kein Fremdsystem |
x-forwarded-for, IP-Adresse | nein | Personenbezug, nur mit Begründung und Löschfrist |
error.message als Freitext | nein | kann Daten aus der Anfrage enthalten |
| Formularinhalte, Request-Body | nein | Inhaltsdaten |
| Nutzerkennung | nur mit Begründung | pseudonym, aber personenbezogen, Löschfrist festlegen |
Die Löschfrist trägt Ihr Verantwortlicher ein, sie hängt vom Zweck ab. Ich liefere die Feldliste und die Konfiguration des Log-Ziels, sodass die Frist technisch durchgesetzt wird.
Wenn doch Personendaten im Log landen
Ein Log mit E-Mail-Adressen, das ein Drittanbieter speichert, ist ein Fall, den man bewerten muss. Die LDI NRW erklärt zur Meldepflicht:
- Verletzungen des Schutzes personenbezogener Daten sind der Aufsichtsbehörde unverzüglich, möglichst binnen 72 Stunden, zu melden, wenn mehr als nur ein geringes Risiko für die Betroffenen besteht (Art. 33 DS-GVO).
- Bei hohem Risiko sind zusätzlich die Betroffenen zu informieren (Art. 34 DS-GVO).
- Jede Verletzung ist intern zu dokumentieren, auch wenn keine Meldung nötig ist (Art. 33 Abs. 5 DS-GVO).
- Passiert die Verletzung bei einem Auftragsverarbeiter, muss er den Verantwortlichen unverzüglich informieren. Der Verantwortliche prüft dann seine Pflichten.
- Die LDI NRW stellt dafür ein Meldeformular auf ihrer Website bereit.
Zwei Folgen für den Aufbau. Erstens: Der Anbieter Ihres Log- oder Fehlerdienstes ist in der Regel Auftragsverarbeiter, und der Vertrag sollte regeln, wie schnell er Sie informiert. Zweitens: Wer die Zeile im Log von vornherein klein hält, hat im Ernstfall weniger zu bewerten. Ob in einem konkreten Fall eine Meldung nötig ist, entscheiden Sie mit Ihrer Rechtsberatung oder Ihrer Datenschutzbeauftragten. Das ist keine Rechtsberatung.
Alarme, die nicht ermüden
Alarme sind in der Next.js-Dokumentation kein Thema. Was jetzt folgt, ist meine Praxis und kein Zitat. Ich halte vier Auslöser für sinnvoll, alle ohne feste Schwellenwerte, die ich Ihnen aus der Luft nennen müsste:
- Neue Fehlergruppe. Ein
digestoder eine Kombination aus Route und Fehlertyp, die es in der vorigen Version nicht gab. Das ist das stärkste Signal nach einem Release. - Auffälliger Anstieg je
routeType. Fehler in Server Actions (action) treffen Formulare und Bestellungen, Fehler beimrenderbetreffen Seiten. - Ein Prüfaufruf mit Inhaltsvergleich. Weil gestreamte Fehler Status 200 liefern, ruft ein geplanter Test die wichtigen Seiten ab und sucht einen festen Text, nicht nur den Statuscode.
- Anstieg bei 404 auf Routen, die es geben sollte. Ein Datenfehler kann
notFound()auslösen. Dann sieht die Seite nach einem Fehler wie eine fehlende Seite aus.
Alarme gehen an eine benannte Person, und zu jedem gehört ein kurzer Satz im Betriebshandbuch: was zu prüfen ist, wer entscheidet, wann abgeschaltet wird. Ein Alarm, den niemand zuordnen kann, wird irgendwann ignoriert.
Checkliste vor dem Livegang
| Frage | Warum sie zählt |
|---|---|
Gibt es error.js auf den Routen mit Daten und ein global-error.js im Root? | Sonst zeigt ein Fehler im Layout eine Standardseite |
| Zeigt die Fehlerseite die Nummer an? | Der Support findet den Fall ohne Rückfragen |
Ist der 404-Pfad bewusst gebaut (notFound(), Proxy oder beides)? | Statuscode und noindex hängen vom Zeitpunkt ab |
Schreibt onRequestError aus einer Positivliste? | Cookies und Query-Strings bleiben draußen |
Sind http.url und http.target im Trace geprüft? | Personenbezug kann in URLs stecken |
| Ist eine Löschfrist für das Log festgelegt und technisch umgesetzt? | Gefordert, wenn Personendaten im Protokoll stehen |
| Gibt es einen AV-Vertrag mit dem Log-Anbieter? | Er ist Auftragsverarbeiter |
| Prüft ein Test Inhalte statt nur Statuscodes? | Gestreamte Fehler liefern 200 |
| Hat jeder Alarm einen Eigentümer? | Sonst Alarmmüdigkeit |
So läuft ein Projekt mit mir
Ich arbeite allein, aus der Ferne und schriftlich, ohne Termine und Telefonate. Am Anfang steht Ihre Mail mit der Adresse der Anwendung, dem Ziel und der Frist. Ich lese den Code, stelle meine Fragen schriftlich und schicke eine Beschreibung des Umfangs mit den Annahmen. Ich baue auf einer Staging-Umgebung, Sie prüfen dort und geben schriftlich frei, erst dann geht die Anwendung live. Für dieses Thema liefere ich die Fehlerdateien, die instrumentation.ts, die Konfiguration von OpenTelemetry, die Feldliste des Logs für Ihr Verzeichnis der Verarbeitungstätigkeiten und eine Betriebsbeschreibung für Ihr Team. Wollen Sie die laufende Pflege abgeben, beschreibt die Seite Wartung und Support in Essen den Ablauf. Das Layout der Fehlerseiten liefern Sie als Vorlage, ich baue es nach. Ist die Anwendung im Kern eine Inhaltsseite, prüfe ich vorab, ob Astro weniger Betrieb bedeutet, und für den Weg zwischen beiden gibt es die Seite zur Migration zwischen Next.js und Astro in Essen. Für ein PHP-Backend hinter dem Frontend gibt es die Seite zur PHP-Entwicklung in Essen.
Häufige Fragen
Wann greift error.js und wann global-error.js? error.js fängt Fehler in seinem Segment und darunter, aber nicht im layout.js oder template.js desselben Segments. Fehler im Root-Layout fängt nur global-error.js. Diese Datei ersetzt das Layout, braucht eigene html- und body-Tags und kennt keine metadata-Exporte.
Warum zeigt die Fehlerseite nur eine Nummer und nicht die Meldung? Next.js reicht Fehler aus Server Components im Produktivbetrieb nur mit allgemeiner Meldung an den Browser, damit keine Details nach außen gelangen. Die Nummer steht in error.digest und passt zum Eintrag im Server-Log. Wer sie anzeigt, kann einen Fall im Log wiederfinden.
Warum meldet das Monitoring Status 200, obwohl die Seite kaputt ist? Gestreamte Antworten beginnen laut Dokumentation mit Status 200, und der Status ändert sich danach nicht mehr. Ein Fehler, der erst nach dem Streamstart auftritt, erscheint im Statuscode also nicht. Er erscheint in onRequestError. Darum alarmiere ich auf diese Ereignisse und prüfe zusätzlich Inhalte, nicht nur Statuscodes.
Was gehört nicht ins Log? Query-Strings, Cookies, Authorization-Header, IP-Adressen, Formularinhalte und freie Fehlertexte, die Daten aus der Anfrage enthalten können. Das Standard-Datenschutzmodell sieht im Regelfall keine Personen- und Inhaltsdaten im Protokoll vor und verlangt Löschfristen, wenn doch welche darin stehen.
Brauche ich OpenTelemetry? Für reine Fehlermeldungen reicht onRequestError. OpenTelemetry liefert zusätzlich Traces über Anfrage, Rendering und fetch-Aufrufe. Die Next.js-Dokumentation empfiehlt es für die Instrumentierung. Ob der Aufwand für Ihre Anwendung lohnt, kläre ich nach Ihrer Beschreibung schriftlich mit Ihnen.
Gestalten Sie auch die Fehlerseiten? Nein. Layout, Texte und Gestaltung kommen von Ihnen oder Ihrer Agentur. Ich baue die Seiten nach Ihrer Vorlage und verdrahte sie mit den richtigen Dateien und Logs.
Ihre Anwendung in einer E-Mail
Fehler tauchen oft zuerst bei Ihren Kunden auf. Wenn Sie wissen wollen, was Ihre Next.js-Anwendung im Ernstfall meldet und was dabei im Log landet, schreiben Sie mir über das Kontaktformular. Nennen Sie die Adresse der Anwendung, Ihr Ziel, den Wunschtermin und den aktuellen Stack samt Hosting. Ich antworte an Werktagen schriftlich mit meinen Fragen und einer ersten Schätzung, und die ist kostenlos.
Ausgewählte Projekte
Beispiele aus meiner Arbeit.
Fintech Solution: pepegotti.com
Die Website pepegotti.com ist eine moderne Plattform, die sich dem Vertrieb von Möbeln widmet und ein klares, ansprechendes Design mit fortschrittlichen Funk...
Fintech Solution: radio.friko.pl
Radio.friko.pl ist ein Internetradiosender, der in den Jahren 2005-2010 als Teil der Friko.pl-Plattform betrieben wurde und den Nutzern den Zugang zu Musik-S...
Fintech Solution: VECTOR SMART DATA
Vectorsmartdata.net ist eine Website, die für die VECTOR Group entwickelt wurde, einen Anbieter fortschrittlicher Telemetrielösungen, die es ermöglichen, Da...
WordPress Support & Entwicklung in Essen
Brauchen Sie die Leistung: Next.js-Entwickler in Essen?
Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.
Projekt beschreibenWeitere WordPress-Dienste und Wissensbasis entdecken
Migration zu Astro, Next.js und Headless WordPress.
WooCommerce-Synchronisierung mit ERP und Großhandel.
Geschäftsprozessautomatisierung rund um WordPress und Firmensysteme.
Bibliothek konkreter Automatisierungsfälle.
Headless WordPress, Sanity, Strapi und Contentful mit Astro oder Next.js.
Astro, MDX, Edge Delivery und an echtem Traffic gemessene Core Web Vitals.
Individuelle WordPress-Entwicklung und Architektur.
Skalierbare Headless-, ERP- und KI-Architektur für Enterprise.
Verwandte Kategorien
Unterstützende Artikel

Sechs bis sechzehn Wochen für typische Projekte, in vier Phasen: Analyse, Scoping, Build und Umstellung, Tuning. Die Variablen sind Katalogumfang, Anzahl der Integrationen, URL-Erhalt und die Bereitschaft des Redaktionsteams, nicht die Wahl des Frameworks.

Umfassende 4-Jahres-TCO-Analyse (Total Cost of Ownership), reale Core-Web-Vitals-Benchmarks, Astro 7 GraphQL APQ-Architektur und eine 10-Punkte-Entscheidungsmatrix für Enterprise-Entscheider zwischen entkoppeltem und traditionellem WordPress.

Die Entscheidung Shopify Plus vs WooCommerce headless im Jahr 2026 ist kein binärer "Plattform vs Custom"-Kompromiss mehr. Beide laufen headless, beide integrieren KI, beide liefern am Edge aus. Die echten Achsen sind Kontrolle, Gesamtkosten über fünf Jahre und Exit-Strategie. Dieser Artikel durchläuft die Entscheidungsmatrix mit bestätigten Plattformfakten.