React 19 Error Handling Callbacks
React 19 adds root-level callbacks that let applications observe three categories of rendering errors: errors caught by an Error Boundary, errors that escape all boundaries, and errors React recovers from automatically. These callbacks are configured on `createRoot` or `hydrateRoot`, making them useful for centralized error reporting.
`onCaughtError` runs when React catches an error with an Error Boundary. The callback receives the thrown error and an `errorInfo` object containing the React component stack, so an application can send structured diagnostics to an error-reporting service.
`onUncaughtError` runs when an error escapes without being handled by an Error Boundary. This is distinct from `onCaughtError`: the latter represents a boundary successfully taking control of the failed subtree, while the former indicates that no boundary caught the error.
`onRecoverableError` is for errors from which React automatically recovers. It is particularly relevant to rendering and hydration scenarios where React can continue operating after detecting a problem. The callback also receives an `errorInfo` object, and some recoverable errors can expose the underlying cause through `error.cause`.
These callbacks are root configuration options rather than arguments to `root.render()`. For client rendering, configure them in `createRoot(container, options)`; for server-rendered markup, use the corresponding options on `hydrateRoot`. React 19 changed render-error reporting so applications should not depend on the older behavior of render errors being re-thrown for custom reporting.
A senior engineer should treat these callbacks as observability hooks, not replacements for Error Boundaries. Boundaries determine how caught UI failures are handled, while root callbacks provide centralized visibility into React's error lifecycle. A production implementation can attach component-stack information, classify the callback type, filter expected errors, and forward useful events to an error-monitoring system.
Key points
- `onCaughtError` observes errors caught by an Error Boundary.
- `onUncaughtError` observes rendering errors that escape all Error Boundaries.
- `onRecoverableError` observes errors React automatically recovers from.
- Configure the callbacks on `createRoot` or `hydrateRoot`, not `root.render()`.
- `errorInfo.componentStack` provides React component-stack context for the callback.
Interview questions
Where should you configure `onUncaughtError` in a React application?
For a client-rendered application, pass it as an option to `createRoot`. It should not be passed as a second argument to `root.render()`. For server-rendered applications, the analogous configuration belongs on `hydrateRoot`.
What are the three React 19 root error callbacks and when does each run?
`onCaughtError` runs when an Error Boundary catches an error. `onUncaughtError` runs when an error is not caught by an Error Boundary. `onRecoverableError` runs when React detects an error but can recover automatically. All three are configured as root options.
How would you use these callbacks to build production error reporting?
I would register all relevant root callbacks and normalize their events into a common reporting shape. Each event would include the error, callback category, and `errorInfo.componentStack` when available. I would filter known or intentionally ignored failures before sending them to the monitoring service. For recoverable errors, I would still consider reporting because repeated recoveries can reveal rendering or hydration problems.
Why should an application not rely on render errors being re-thrown for custom reporting in React 19?
React 19 changed render-error handling to avoid the previous re-throw behavior that could produce duplicated reporting. Uncaught render errors are reported through the browser's error-reporting mechanism, while caught errors are reported through React's normal error logging behavior. The root callbacks provide explicit application-level hooks for custom reporting instead. This makes error telemetry less dependent on React's internal propagation behavior.
How do `createRoot` and `hydrateRoot` relate to these callbacks?
Both APIs accept the same three root-level error callback options. `createRoot` is used when React owns an initially client-rendered DOM container, while `hydrateRoot` attaches React to HTML produced by server rendering. The callbacks therefore provide a consistent client-side observability interface across ordinary rendering and hydration. `onRecoverableError` is especially useful for observing errors during hydration or other recoverable rendering situations.