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.