const [error, setError] = useState(null);
if (error) throw error; // handled by the nearest boundary
async function handleSave() {
try {
await save();
} catch (e) {
setError(e);
}
}
Catch them locally with try/catch, then store the error in state. To reach a boundary, re-throw the stored error during render.
Local handling. Wrap the async work in try/catch (or .catch). Save the error in state, and render an error message or a retry button. This is usually the best user experience, because the rest of the component keeps working.
Sending it to a boundary. Store the error in state in the catch. In the next render, run if (error) throw error;. Boundaries catch rendering errors, so the nearest one handles it.
Other routes:
- In React 19, if a function passed to
startTransitionthrows, React shows the error in the nearest error boundary. This includes Actions, the async functions you pass tostartTransitionor to a form'saction. - Data libraries such as TanStack Query have options to throw errors to boundaries.
- For unexpected errors, report them to a logging service. React 19's
createRootacceptsonCaughtErrorandonUncaughtErrorfor this.
- Catch errors locally with
try/catchand store them in state. - Re-throw the stored error during render to reach a boundary.
- In React 19, errors thrown in transitions and Actions go to the nearest boundary.
- Data libraries can forward errors to boundaries.
- Log errors with
onCaughtErrorandonUncaughtErroron the root.