# react-error-boundary: a reusable error boundary for every React renderer

> Brian Vaughn's react-error-boundary wraps React's class-based error boundary concept in a reusable component with reset and logging hooks. It is small, MIT licensed, and explicit about what it does not catch.

**bvaughn/react-error-boundary** — Simple reusable React error boundary component

- Repository: https://github.com/bvaughn/react-error-boundary
- Website: https://react-error-boundary-lib.vercel.app
- Stars: 7,991 · Forks: 231
- Language: TypeScript
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/bvaughn-react-error-boundary

## The problem react-error-boundary removes

React's error boundary is a class component concept. To use it you write a class, implement componentDidCatch or getDerivedStateFromError, keep an error in state, and decide how a child can clear that state and retry. That code is nearly identical in every application, and it is easy to get the retry path wrong. react-error-boundary exists so that logic lives in one place. The package describes itself as a simple reusable React error boundary component, and the README notes it supports all React renderers, including React DOM and React Native. That renderer-agnostic claim matters if you share components between web and native targets, because the boundary itself does not reach for DOM APIs. The audience is React application developers who want a fallback UI around a subtree, a way to log the thrown value and the component stack, and a reset button that actually re-renders the failed tree. It is not a global error handler and it is not a replacement for a reporting service; it is the component that decides what the user sees when rendering fails.

## How the boundary catches, reports and resets

The component builds on React error boundaries, so it inherits React's rules about what is caught. Errors thrown while rendering the tree below the boundary are caught. The README lists what is not caught: server side rendering, event handlers, errors thrown in the error boundary itself, and async code that runs after rendering, such as setTimeout callbacks or unresolved promises. That list is the most important paragraph in the documentation, because it defines the boundary of the boundary. For the gaps there is a second mechanism. useErrorBoundary passes a caught error to the nearest boundary, and in React 19 errors thrown from a function passed to the startTransition function returned by useTransition are caught by the nearest boundary. Reporting is handled by onError, which receives the thrown value and a React component stack identifying where the error was thrown. Reset is handled by onReset, called when a boundary is reset so React can retry the failed render, and by resetKeys, which resets a triggered boundary when the listed keys change. The fallback can be supplied three ways: fallback for static content, FallbackComponent for a component, or fallbackRender for a render prop that receives error and resetErrorBoundary. The README tells you to consult the documentation to decide which fits, which is a fair admission that three options need guidance.

## Install react error boundary and render a first fallback

The README gives three package manager commands and no configuration step. Pick the one that matches your project.

```bash
# npm
npm install react-error-boundary

# pnpm
pnpm add react-error-boundary

# yarn
yarn add react-error-boundary
```

The quick start wraps an ErrorBoundary around the part of the tree where a fallback should appear. The fallback render prop receives error and resetErrorBoundary, and the button calls the latter to clear the error and retry rendering. onError is where you would forward the error to a reporting service, and onReset is where you reset state that may have caused the failure. Note the "use client" directive at the top: the README states this is a client component, and that you can only pass props to it that are serializable or use it in files with that directive.

```tsx
"use client";

import { ErrorBoundary, getErrorMessage } from "react-error-boundary";

export default function App() {
  return (
    <ErrorBoundary
      fallbackRender={({ error, resetErrorBoundary }) => (
        <div role="alert">
          <p>Something went wrong:</p>
          <pre>{getErrorMessage(error)}</pre>
          <button onClick={resetErrorBoundary}>Try again</button>
        </div>
      )}
      onError={(error, info) => {
        // Log the error to your error reporting service
      }}
      onReset={() => {
        // Reset any state that may have caused the error
      }}
    >
      {/* Components protected by this boundary */}
    </ErrorBoundary>
  );
}
```

The README does not list any required props, so an ErrorBoundary with no fallback props is syntactically valid. In practice you want at least one of fallback, FallbackComponent or fallbackRender, otherwise the boundary has nothing to show. The package ships as ESM, with main pointing at dist/react-error-boundary.cjs and module at dist/react-error-boundary.js, so both CommonJS and ES Module consumers have an entry point.

## What the boundary will not catch, and when to use something else

The documented exclusions are the real limitation. A failed fetch inside a click handler will not reach the boundary. A rejected promise that nobody awaits will not reach it. A crash during server side rendering will not reach it. If your application's failures are mostly of that kind, an error boundary is the wrong tool and you will spend time wondering why the fallback never appears. The README points at two remedies: useErrorBoundary to push caught errors to the nearest boundary, and useTransition in React 19 for errors thrown from a function passed to startTransition. Both require you to change the code that throws, which means adoption is not purely a matter of wrapping a subtree. There is also a version boundary. The README warns that projects using frameworks or runtimes that do not support ES Modules should use version 5 of the library, so on an older toolchain the current release is not the one you install. The FAQ addresses another failure mode: an "ErrorBoundary cannot be used as a JSX component" error can be caused by a version mismatch between react and @types/react, and the fix is to make both match exactly. That is a TypeScript and types problem, not a runtime problem, but it is the error a new user is most likely to hit.

## react-error-boundary compared with Suspense and hand-rolled boundaries

The closest thing in React itself is Suspense, and the two solve different problems. Suspense handles a pending state: a component is not ready yet, so React shows a fallback until it is. An error boundary handles a failure state: rendering threw, so React shows a fallback instead of unmounting the tree. A common pattern is to nest them, with Suspense inside the boundary, but they are not alternatives to each other and the search phrasing that pits them against one another is misleading. The genuine alternative is writing the class yourself. A hand-rolled boundary is perhaps thirty lines: state holding the error, a static getDerivedStateFromError, a componentDidCatch that calls your logger, and a reset method you wire to a button. What you give up by hand-rolling is the reset contract. react-error-boundary exposes resetErrorBoundary to the fallback, calls onReset when a reset happens, and resets automatically when resetKeys change. Reproducing that consistently across a codebase is where hand-rolled versions drift. What you gain by hand-rolling is zero dependencies and full control over the class, which some teams prefer for a component this small. There is no third-party comparison to make here: the package is a thin wrapper over a React primitive, so the decision is wrapper versus your own wrapper, not library versus library.

## Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-20, two days before this writing. Releases are frequent and small: 6.1.6 on 2026-09-20, 6.1.5 on 2026-09-05, 6.1.4 on 2026-08-30. That cadence suggests patch-level maintenance rather than a rewrite in progress, and the CHANGELOG.md at the repository root is where the specifics live. The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive licence, but it is not legal advice and it does not cover your own dependencies, so check how the package is attributed in your build output if your organisation tracks licences. Upgrade cost is low in normal cases because the public surface is a component, three fallback props, two callbacks, resetKeys and useErrorBoundary. The upgrade risk sits at the edges: the ESM requirement that pushes older runtimes to version 5, and the react versus @types/react version match that the FAQ calls out. Before upgrading, align those two packages exactly and confirm your bundler handles the module entry. The repository also carries integrations/, pnpm-workspace.yaml and a Vite setup, so the maintainer tests against a real integration rather than only unit tests.

## Verifying react-error-boundary in your own app

The repository uses vitest for tests, with test:ci running vitest run and test:debug attaching an inspector on port 3000. That tells you how the library is tested, not how you should test your usage. The practical check is to render a component that throws during render inside the boundary and confirm the fallback appears and the reset button works. Then confirm the negative case: throw inside an onClick handler and verify the boundary does not catch it, because that is the behaviour the README documents and the one most likely to surprise a team. If you use the App Router or another framework with a server rendering step, verify the boundary sits in a client component, since the README states it is a client component and that props must be serializable or the file must carry the "use client" directive. Logging deserves its own check: make onError write the error and the component stack somewhere you can read, otherwise the boundary hides failures from your reporting instead of surfacing them. The documentation site at react-error-boundary-lib.vercel.app has an API reference, examples and a common questions guide, and the README points there rather than duplicating the material.

## Conclusion

Adopt react-error-boundary if you want a maintained, MIT licensed boundary with reset semantics instead of hand-writing componentDidCatch in every project. Do not adopt it expecting it to catch event handler, async or server-side rendering errors, because the README states it does not. Before shipping, verify your React and @types/react versions match exactly, since the README attributes the 'cannot be used as a JSX component' error to a mismatch between them, and check whether your framework supports ES Modules, because the README says projects on runtimes without ESM support should use version 5.

## FAQ

### What is an error boundary in React?

An error boundary is a React component that catches errors thrown while rendering the tree below it and renders a fallback UI instead. The README links to React's own documentation on catching rendering errors with an error boundary, and react-error-boundary is a reusable implementation of that concept.

### Is there an NPM package for React error boundaries?

Yes. react-error-boundary is published as an npm package, and the README gives npm install react-error-boundary along with pnpm add and yarn add equivalents.

### How do I install react-error-boundary?

Run npm install react-error-boundary, or pnpm add react-error-boundary, or yarn add react-error-boundary. There is no additional setup step in the README beyond importing ErrorBoundary from the package.

### How do I use react-error-boundary?

Wrap an ErrorBoundary around the part of the tree where you want a fallback, and supply fallback, FallbackComponent or fallbackRender. The fallback can call resetErrorBoundary to clear the error and retry rendering, and onError receives the thrown value plus the component stack.

### How do I trigger react-error-boundary to test it?

The README does not give a testing recipe, but it states that errors thrown while rendering the tree below the boundary are caught. Throwing during render is therefore the case the boundary is designed for; throwing inside an event handler is not, and useErrorBoundary is the documented way to route those errors to the nearest boundary.

### Is react-error-boundary an alternative to Suspense?

No, they cover different states. Suspense shows a fallback while content is pending, while an error boundary shows a fallback when rendering throws. The README describes the boundary only in terms of catching errors, and does not present it as a Suspense replacement.

## Sources

- [bvaughn/react-error-boundary on GitHub](https://github.com/bvaughn/react-error-boundary)
- [License: MIT](https://github.com/bvaughn/react-error-boundary/blob/main/LICENSE)
- [Project website](https://react-error-boundary-lib.vercel.app)
- [README](https://github.com/bvaughn/react-error-boundary/blob/main/README.md)
- [Releases](https://github.com/bvaughn/react-error-boundary/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bvaughn-react-error-boundary
