Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
IT NachrichtenPensions Awareness Ireland launches AI retirement coach(21.09.2026 um 10:08 Uhr)
IT NachrichtenVMware has quietly walked back its SmartNIC ambitions(21.09.2026 um 09:02 Uhr)
IT NachrichtenYour cloud survived everything except the real world(21.09.2026 um 10:03 Uhr)
IT NachrichtenZeitreise ins Jahr 2016: Gadgets, die jeder haben wollte(21.09.2026 um 10:10 Uhr)
IT NachrichtenPensions Awareness Ireland launches AI retirement coach(21.09.2026 um 10:08 Uhr)
IT NachrichtenVMware has quietly walked back its SmartNIC ambitions(21.09.2026 um 09:02 Uhr)
IT NachrichtenYour cloud survived everything except the real world(21.09.2026 um 10:03 Uhr)
IT NachrichtenZeitreise ins Jahr 2016: Gadgets, die jeder haben wollte(21.09.2026 um 10:10 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Error Boundaries in Next.js App Router — Handling Failures Gracefully

Most Next.js applications handle the happy path well. A request comes in, data loads, components render, user sees the page. Error handling is where applications often reveal their real quality — and where App Router introduces some n…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Most Next.js applications handle the happy path well. A request comes in, data loads, components render, user sees the page. Error handling is where applications often reveal their real quality — and where App Router introduces some nuances worth understanding.



Here's how error boundaries work in App Router, what the error.js file actually does, and the patterns that make failure handling feel intentional rather than afterthought. This is the approach I use in production for a free AI image generator for beginners where graceful degradation matters more than on sites with simpler data flows.









What Changes in App Router



Pages Router had _error.js and getInitialProps for error handling. App Router introduces a different model built on React's Error Boundary concept, with error.js files that can be nested at any level of the route hierarchy.



The key mental model shift: errors are contained at the nearest error.js boundary, not propagated to a global handler. This means you can have different error UIs for different sections of your app.









The error.js File



Place an error.js file in any route segment to catch errors in that segment and its children:




app/
├── layout.js # Root layout
├── error.js # Catches errors in root segment
├── page.js
├── dashboard/
│ ├── error.js # Catches errors in dashboard only
│ ├── layout.js
│ └── page.js
└── blog/
├── error.js # Catches errors in blog only
└── [slug]/
└── page.js









// app/error.js
'use client'; // Error components must be Client Components

import { useEffect } from 'react';

export default function Error({ error, reset }) {
useEffect(() => {
// Log to error reporting service
console.error(error);
}, [error]);

return (
<div className="flex flex-col items-center justify-center
min-h-[400px] gap-4 p-6 text-center">
<h2 className="text-xl font-semibold text-foreground">
Something went wrong
</h2>
<p className="text-sm text-muted max-w-sm">
{error.message || 'An unexpected error occurred.'}
</p>
<button
onClick={reset}
className="px-4 py-2 bg-orange-500 text-white
rounded-full text-sm font-medium
hover:bg-orange-600 transition-colors"
>
Try again
</button>
</div>
);
}






Important: error.js must be a Client Component ('use client'). React Error Boundaries are a client-side concept — server errors get converted to client-side error events before reaching the boundary.



The reset function retries the failed render. Use it for transient errors (network issues, temporary service failures) rather than permanent ones.









The reset Function — When to Show It



The reset button only makes sense for errors that might succeed on retry:




export default function Error({ error, reset }) {
// Check if error is retryable
const isRetryable = error.digest !== 'NEXT_NOT_FOUND';

return (
<div className="error-container">
<h2>Something went wrong</h2>
<p>{getErrorMessage(error)}</p>

{isRetryable && (
<button onClick={reset}>Try again</button>
)}

{!isRetryable && (
<a href="/">Return home</a>
)}
</div>
);
}

function getErrorMessage(error) {
if (error.message?.includes('fetch')) {
return 'Failed to load data. Check your connection.';
}
if (error.message?.includes('timeout')) {
return 'Request timed out. Please try again.';
}
return 'An unexpected error occurred.';
}












Global Error Handling — global-error.js



The root error.js doesn't catch errors in the root layout.js. For that, you need global-error.js:




// app/global-error.js
'use client';

export default function GlobalError({ error, reset }) {
return (
<html>
<body>
<div className="global-error">
<h1>Application Error</h1>
<p>Something went wrong at the application level.</p>
<button onClick={reset}>Reload</button>
</div>
</body>
</html>
);
}






global-error.js replaces the root layout when it renders, so it needs to include <html> and <body> tags. This is the last-resort catch for errors that escape all other boundaries.









Server Component Error Handling



Server components can throw errors directly, but handling them well requires a pattern slightly different from what you might expect:




// app/blog/[slug]/page.js
async function getBlogPost(slug) {
const response = await fetch(`/api/posts/${slug}`);

if (response.status === 404) {
notFound(); // Triggers not-found.js, not error.js
}

if (!response.ok) {
throw new Error(`Failed to fetch post: ${response.status}`);
// This triggers error.js
}

return response.json();
}

export default async function BlogPost({ params }) {
const post = await getBlogPost(params.slug);
return <PostContent post={post} />;
}






notFound() vs throw Error(): Use notFound() for expected missing resources — it renders not-found.js and returns a 404 status. Use throw for unexpected failures — it renders error.js.









The not-found.js File



For 404-style errors, not-found.js provides a cleaner separation than error.js:




// app/not-found.js
import Link from 'next/link';

export default function NotFound() {
return (
<div className="flex flex-col items-center justify-center
min-h-[400px] gap-4 text-center p-6">
<h2 className="text-2xl font-semibold">Page not found</h2>
<p className="text-muted text-sm">
The page you're looking for doesn't exist or has been moved.
</p>
<Link
href="/"
className="px-4 py-2 bg-foreground text-background
rounded-full text-sm font-medium"
>
Return home
</Link>
</div>
);
}












Error Boundaries for Async Operations in Client Components



Client components that fetch data need their own error handling since they're outside the server component error flow:




'use client';
import { useState, useEffect } from 'react';

export function DataFetcher({ url }) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
async function fetchData() {
try {
setLoading(true);
setError(null);
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const json = await response.json();
setData(json);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}

fetchData();
}, [url]);

if (loading) return <Skeleton />;

if (error) return (
<div className="error-inline">
<p className="text-sm text-red-500">{error}</p>
<button
onClick={() => fetchData()}
className="text-xs text-muted hover:text-foreground"
>
Retry
</button>
</div>
);

return <DataDisplay data={data} />;
}












Error Reporting Integration



error.js is the right place to integrate with error monitoring:




'use client';
import { useEffect } from 'react';

export default function Error({ error, reset }) {
useEffect(() => {
// Send to your error monitoring service
reportError({
message: error.message,
digest: error.digest, // Next.js server error ID
stack: error.stack,
timestamp: new Date().toISOString(),
path: window.location.pathname,
});
}, [error]);

return (
// Error UI
);
}

async function reportError(errorData) {
try {
await fetch('/api/errors', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(errorData),
});
} catch {
// Don't let error reporting itself cause more errors
console.error('Failed to report error:', errorData);
}
}






The error.digest is particularly useful — it's a hash that Next.js uses to identify server-side errors in logs without exposing sensitive stack traces to the client.









The Error Boundary Hierarchy in Practice



For a real application, the error boundary structure might look like:




global-error.js        ← Last resort, includes <html>
├── error.js ← Root-level errors
│ ├── (auth)/
│ │ └── error.js ← Auth-specific errors
│ ├── dashboard/
│ │ └── error.js ← Dashboard-specific errors
│ └── api/
│ └── route.js ← API routes handle their own errors






This lets you show relevant error messages — "Your session expired, please log in again" for auth errors, "Failed to load dashboard data" for dashboard errors — rather than a generic "something went wrong" for everything.









What I Built This On



This error handling pattern runs in production on pixova.io. The generation pipeline has several async steps where things can go wrong — API timeouts, inference failures, upload errors — and the error boundary setup means failures at each step show appropriate messages rather than breaking the whole page.



The reset button is particularly important for generation tools where users are mid-workflow when something fails — it retries without losing the prompt they just wrote.



Questions on specific error scenarios? Drop them in the comments.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Error Boundaries in Next.js App Router — Handling Failures Gracefully

Thematisch verwandte Begriffe: Error, Boundaries, Nextjs, Router · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94030 | A security vulnerability has been detected in SerenityOS up to 3d83e4509…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick