ErrorBoundary

Your safety net for render crashes. A class component with one job: catch render-time failures in descendants and show a fallback instead of a blank screen. Pair it with <ErrorState> for ready-made fallbacks. Where boundaries should go lives in /error-handling; this page covers how it works, plus the visuals.

Live demo

A boundary wrapped around a small section. Hit Detonate and the section throws mid-render — the boundary catches it and shows the section-scope fallback. Reset clears the caught error so you can blow it up again.

Everything in here is happy. Click Detonate below and the render throws — the boundary catches it and shows the section-scope ErrorState.

Usage

Static fallbacktsx
import { ErrorBoundary, ErrorState } from '@halo-compliance/ui'

<ErrorBoundary fallback={<ErrorState scope="section" />}>
  <RiskyChild />
</ErrorBoundary>
Render-prop fallback (uses the captured error + reset callback)tsx
<ErrorBoundary
  fallback={({ error, reset }) => (
    <ErrorState
      scope="section"
      title="Couldn't load this region"
      message={error.message}
      onReset={reset}
    />
  )}
>
  <RiskyChild />
</ErrorBoundary>
Auto-reset on route changetsx
// Pass a resetKey that changes per route, so a crash on one route
// doesn't persist into the next.
<ErrorBoundary
  resetKey={location.pathname}
  fallback={<ErrorState scope="page" />}
>
  {children}
</ErrorBoundary>

Props

fallback
ReactNode | ({ error, reset }) => ReactNode

REQUIRED Static node OR a render-prop. Use the render-prop when the fallback needs the captured error or wants to expose a reset button.

onError
(error, info) => void

Optional reporter — fires once per catch. Wire to Sentry or your telemetry.

resetKey
unknown

When this prop value changes, the boundary auto-resets to non-error state. Pair with the current route key for boundary-per-route behavior.

children
ReactNode

REQUIRED The subtree to catch errors in.

Caveats

React error boundaries cannot catch errors in:

  • Event handlers (use try/catch inside the handler and surface via a toast).
  • Async callbacks / Promise rejections (handle in the async chain).
  • Server-rendered HTML errors (handle at the framework level).
  • Errors thrown in the boundary itself or its fallback. Keep fallbacks dumb — string interpolation, no fetches.