---
id: "packages/active-ui/error-boundary"
title: "ErrorBoundary"
description: "Catches a render error in part of the page and renders your fallback, with a reset that tries again."
url: "/packages/active-ui/error-boundary"
locale: "en"
revision: "6f32a128fb78bb84"
---

# ErrorBoundary

`ErrorBoundary` catches an error thrown while its children render, and renders the `fallback` you
give it instead. The fallback receives the error and a `reset` that renders the children again.
The boundary draws nothing itself.

**Example: A render error caught in one area**

Client: Runs entirely in your browser. Source: `examples/ui/error-boundary.tsx`.

```tsx
// apps/docs/examples/ui/error-boundary.tsx
'use client';

import {useState} from 'react';

import {ErrorBoundary} from '@workspace/active-ui/components/composed/error-boundary';
import {
  Alert,
  AlertDescription,
  AlertTitle,
} from '@workspace/active-ui/components/primitives/alert';
import {Button} from '@workspace/active-ui/components/primitives/button';

function Totals({broken}: {broken: boolean}) {
  if (broken) {
    // A deliberate render error, to show the boundary at work.
    throw new Error('The totals could not be calculated.');
  }
  return <p className="text-sm">Total contributions this year: 48,210.00</p>;
}

/**
 * A render error caught in one area of the page. Break the area: the
 * boundary shows the fallback with the error's message and a retry that
 * renders the area again. The error is real, but harmless.
 */
export default function ErrorBoundaryExample() {
  const [broken, setBroken] = useState(false);
  const [caught, setCaught] = useState(0);
  return (
    <div className="grid w-full max-w-md gap-4">
      <Button
        variant="outline"
        className="justify-self-start"
        onClick={() => setBroken(true)}
      >
        Break the totals
      </Button>
      <ErrorBoundary
        onError={() => setCaught((count) => count + 1)}
        onReset={() => setBroken(false)}
        fallback={(error, reset) => (
          <Alert variant="destructive">
            <AlertTitle>This area failed</AlertTitle>
            <AlertDescription>
              <p>{error.message}</p>
              <Button size="sm" variant="outline" onClick={reset}>
                Try again
              </Button>
            </AlertDescription>
          </Alert>
        )}
      >
        <Totals broken={broken} />
      </ErrorBoundary>
      <p className="text-muted-foreground text-xs">
        Errors reported to <code>onError</code>: {caught}
      </p>
    </div>
  );
}
```

## What the composition adds

- **A function as fallback**, `(error, reset) => ReactNode`, so a retry inside it really resets the
  boundary.
- **`onError`** to log or report the error, and **`onReset`** to clean up before the children
  render again, as the example does by repairing what broke.

Like every React error boundary, it does not catch errors in event handlers, in asynchronous code
or on the server. React still reports a caught error in the browser console, as the example shows when you
break it.

## Usage

```tsx
import {ErrorBoundary} from '@workspace/active-ui/components/composed/error-boundary';

<ErrorBoundary
  onError={(error) => report(error)}
  fallback={(error, reset) => (
    <Alert variant="destructive">
      <AlertTitle>This area failed</AlertTitle>
      <AlertDescription>
        <Button onClick={reset}>Try again</Button>
      </AlertDescription>
    </Alert>
  )}
>
  <Totals />
</ErrorBoundary>;
```

## What your application provides

- The fallback and its text: an [Alert](/packages/active-ui/alert) for an area, an
  [ErrorScreen](/packages/active-ui/notice-screen) for a whole page.
- Logging in `onError`, and what must change in `onReset` so the next render does not fail again.

## API

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | yes | The content that may throw while rendering. |
| `fallback` | `(error: Error, reset: () => void) => ReactNode` | yes | What is rendered as soon as an error is caught.  `reset` clears the error state and renders `children` again; call it from a retry action in the fallback. |
| `onError` | `((error: Error, errorInfo: ErrorInfo) => void)` | no | Side effect on catching: logging, reporting, counting. |
| `onReset` | `(() => void)` | no | Runs before the error state is cleared, so the caller can clean up. |

**ErrorBoundaryProps**

```ts
interface ErrorBoundaryProps {
  children: ReactNode;
  fallback: (error: Error, reset: () => void) => ReactNode;
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
  onReset?: () => void;
}
```
