- Next.js
- App Router File Conventions
- Granular Error Handling with error.tsx and global-error.tsx
Granular Error Handling with error.tsx and global-error.tsx
error.tsx defines an isolated React Error Boundary around sibling page segments, allowing crashes to be caught without breaking the outer layout. It must be a Client Component and receives error and reset props. To catch errors in the root layout itself, Next.js requires global-error.tsx defining its own <html> and <body> tags.
Learning Objectives
Explain why error.tsx must always be a Client Component ("use client").
Implement error recovery mechanisms using the reset() function.
Understand why error.tsx cannot catch errors thrown inside its sibling layout.tsx.
Implement global-error.tsx to catch root layout crashes in production.
Prerequisites & Background Knowledge
Why Interviewers Care
Critical for production resilience and enterprise fault tolerance questions in senior interview loops.
The Challenge
Why must error.tsx be a Client Component? Why can error.tsx NOT catch errors thrown in sibling layout.tsx files, and how does global-error.tsx solve root layout failures?
Code Architecture & Implementation
1// app/dashboard/error.tsx2// MUST BE A CLIENT COMPONENT3'use client';45import { useEffect } from 'react';67export default function DashboardError({8 error,9 reset,10}: {11 error: Error & { digest?: string };12 reset: () => void;13}) {14 useEffect(() => {15 // Log error to Sentry / Datadog16 console.error('Captured dashboard error:', error);17 }, [error]);1819 return (20 <div className="error-card">21 <h2>Failed to load analytics dashboard</h2>22 <p>Error digest: {error.digest || 'Unknown'}</p>23 {/* reset() re-renders the segment, attempting recovery */}24 <button onClick={() => reset()}>Try Again</button>25 </div>26 );27}2829// app/global-error.tsx30// Catches errors in the ROOT layout. Must define <html> and <body>.31'use client';3233export default function GlobalError({34 error,35 reset,36}: {37 error: Error & { digest?: string };38 reset: () => void;39}) {40 return (41 <html lang="en">42 <body>43 <div className="fatal-error-screen">44 <h1>Critical System Error</h1>45 <button onClick={() => reset()}>Restart Application</button>46 </div>47 </body>48 </html>49 );50}
Architectural Explanation
Why error.tsx Must Be a Client Component
React Error Boundaries require the lifecycle methods componentDidCatch or getDerivedStateFromError, which only exist in client React. A Server Component cannot maintain client error boundary state.
The Layout-Error Scoping Rule
Look at the generated component tree:
<Layout>
<ErrorBoundary fallback={<Error />}>
<Page />
</ErrorBoundary>
</Layout>Notice that <ErrorBoundary> is rendered inside <Layout>:
- An error thrown inside
page.tsxis caught byerror.tsx. The navigation layout remains functional! - An error thrown inside
layout.tsxcannot be caught by its siblingerror.tsx, because the error boundary is its child. - To catch an error in
layout.tsx, you must place anerror.tsxin the parent directory segment.
The Role of global-error.tsx
Because the root app/layout.tsx has no parent folder, a crash in the root layout cannot be caught by app/error.tsx.
Next.js provides app/global-error.tsx specifically for this failure mode:
- It replaces the entire document on root crash.
- It must define its own
<html>and<body>tags. - It only triggers in production builds (in development, the Next.js error overlay displays instead).
Common Mistakes & Anti-Patterns
Omitting "use client" in error.tsx, causing a compile error.
Expecting app/error.tsx to catch errors thrown in app/layout.tsx.
Forgetting that global-error.tsx must provide <html> and <body> tags.
Interview Follow-Up Traps
Interviewer asks: "Does the error object in error.tsx contain full server stack traces in production?" Trap answer: Yes, for debugging. Correct answer: No! In production, Next.js strips sensitive stack traces and error messages for security, providing only a generic error and an error.digest hash to correlate with server logs.
Interviewer asks: "Does calling reset() perform a full browser reload?" Trap answer: Yes. Correct answer: No! reset() executes a soft client re-render of the error boundary segment.
Frequently Asked Questions
Can you have nested error boundaries in App Router?
Yes. Placing error.tsx at multiple folder levels allows granular fallbacks for sub-features while keeping the parent UI intact.
Does error.tsx catch 404 Not Found errors?
No. Not Found errors are handled specifically by not-found.tsx.
Why does global-error.tsx only run in production?
In local development, Next.js displays the rich Fast Refresh error overlay to aid debugging.
Can reset() resolve transient network failures?
Yes. If a transient network blip caused the initial fetch to fail, calling reset() re-executes the server fetch.
