C.W.K.
Stream
Lesson 09 of 09 · published

Error Handling Patterns

~20 min · error.tsx, global-error.tsx, boundaries

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The boundary hierarchy

app/global-error.tsx       # catches root layout errors
  app/layout.tsx
    app/dashboard/error.tsx # catches dashboard page + below
      app/dashboard/page.tsx
        components

error.tsx — per-segment

Errors in the page or descendants bubble up to the nearest error.tsx. It must be a Client Component (uses hooks). Never catches errors in its own layout — put the boundary in the parent for that.

global-error.tsx — for root layout failures

Lives at app/global-error.tsx. Renders its own <html> and <body> because it replaces the broken root layout entirely.

Reporting

Wire error objects into Sentry / Datadog / your logger inside the boundary. The framework gives you an error.digest — that's the same id surfaced in server logs, so you can correlate user reports with traces.

Code

Per-segment error boundary·tsx
// app/dashboard/error.tsx
'use client';
import { useEffect } from 'react';

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // ship to your logger; digest matches server logs
    console.error({ digest: error.digest, message: error.message });
  }, [error]);
  return (
    <div className="p-6 text-center">
      <h2 className="text-lg font-semibold">Something went wrong</h2>
      <p className="mt-1 text-sm text-gray-500">{error.message}</p>
      <button onClick={() => reset()} className="mt-4 rounded bg-blue-600 px-3 py-1 text-white">
        Try again
      </button>
    </div>
  );
}
Global error replaces the root layout·tsx
// app/global-error.tsx
'use client';
export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <html>
      <body>
        <h1>Something went very wrong</h1>
        <p>{error.digest}</p>
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  );
}

External links

Exercise

Add error.tsx at three levels (root, dashboard, settings). Throw an error from a deep page and confirm the closest boundary catches it. Verify the digest in the boundary matches the digest in your terminal logs.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.