# React error boundary wraps main application

- **Pattern:** `ab-002287` (`saas-error-handling.error-boundaries.react-error-boundary`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002287
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002287)

## Why it matters

Without a root-level error boundary, a single thrown exception in any React component silently blanks the entire application — users see a white screen with no explanation and no recovery path. CWE-755 (Improper Handling of Exceptional Conditions) names this directly: the absence of fault tolerance at the application boundary turns transient bugs into total outages. For Next.js App Router projects, a route-level `error.tsx` alone is insufficient — errors in the root layout bypass it entirely, requiring `global-error.tsx` as a separate boundary. ISO 25010 reliability.fault-tolerance classifies the absence of this pattern as a direct reliability failure.

## Severity rationale

Critical because a missing root boundary converts any unhandled render exception into a full application crash with no user-visible recovery path.

## Remediation

Add both `app/global-error.tsx` and `app/error.tsx` for Next.js App Router — the global file is mandatory because route-level boundaries don't cover root layout errors.

```tsx
// app/global-error.tsx
'use client'
export default function GlobalError({ error, reset }: { error: Error; reset: () => void }) {
  return (
    <html>
      <body>
        <h2>Something went wrong</h2>
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  )
}
```

For non-Next.js React apps, wrap the root render point with `react-error-boundary`. Verify by intentionally throwing in a component during development and confirming the fallback UI appears instead of a blank page.

## Detection

- **ID:** `react-error-boundary`
- **Severity:** `critical`
- **What to look for:** Examine whether the application has a top-level error boundary covering the main component tree. For Next.js App Router: check for `src/app/error.tsx` or `app/error.tsx` (the route-level error boundary) AND `src/app/global-error.tsx` or `app/global-error.tsx` (the root layout error boundary). For Next.js Pages Router: check for `pages/_error.tsx`. For other React apps (Vite/CRA/Remix/Gatsby): look for a component that extends `React.Component` and implements `componentDidCatch`/`getDerivedStateFromError`, or imports from `react-error-boundary`. Check whether the boundary wraps the root render point (e.g., `<App />` in `main.tsx` or equivalent).
- **Pass criteria:** Count all error boundary files in the project (error.tsx, global-error.tsx, _error.tsx, ErrorBoundary components). Pass if a root-level error boundary exists and wraps the primary application tree. For Next.js App Router, pass if both `error.tsx` (for route errors) and `global-error.tsx` (for root layout errors) are present — at least 2 boundary files required. For Pages Router, pass if `pages/_error.tsx` exists. For other React apps, pass if an `ErrorBoundary` component wraps `<App />` or the equivalent root component. Report even on pass: "Found X error boundary files covering Y route segments."
- **Fail criteria:** Fail if no error boundary exists at the application root. For Next.js App Router, fail if `global-error.tsx` is absent (route-level `error.tsx` alone is insufficient — it doesn't catch errors in the root layout). Do NOT pass when only a route-level `error.tsx` exists without `global-error.tsx` — root layout errors will crash the entire app with no fallback.
- **Cross-reference:** For error boundary fallback UI quality, see the error-boundaries-fallback-ui check in this audit.
- **Skip (N/A) when:** The project has no React dependency. Signal: `react` absent from `package.json` dependencies/devDependencies, no `.jsx`/`.tsx` files present, and framework is not Next.js/Remix/Gatsby/Vite-React.
- **Detail on fail:** Identify which boundary type is missing (e.g., "global-error.tsx not found; route-level error.tsx exists but does not catch root layout errors" or "No ErrorBoundary wrapping root component in main.tsx"). Max 500 chars.
- **Remediation:** Your application has no safety net for unexpected rendering errors. When any component throws, the entire page goes blank with no user feedback.

  For Next.js App Router, create both files:

  ```tsx
  // app/global-error.tsx
  'use client'
  export default function GlobalError({ error, reset }: { error: Error; reset: () => void }) {
    return (
      <html>
        <body>
          <h2>Something went wrong</h2>
          <button onClick={() => reset()}>Try again</button>
        </body>
      </html>
    )
  }
  ```

  ```tsx
  // app/error.tsx
  'use client'
  export default function Error({ error, reset }: { error: Error; reset: () => void }) {
    return (
      <div>
        <h2>Something went wrong</h2>
        <button onClick={() => reset()}>Try again</button>
      </div>
    )
  }
  ```

  For non-Next.js React apps, wrap your root render with `react-error-boundary`:

  ```tsx
  import { ErrorBoundary } from 'react-error-boundary'
  <ErrorBoundary fallback={<div>Something went wrong. <button onClick={() => window.location.reload()}>Reload</button></div>}>
    <App />
  </ErrorBoundary>
  ```

  Verify by intentionally throwing in a component and confirming the fallback UI renders instead of a blank page.

---

## External references

- cwe CWE-755
- iso-25010 reliability.fault-tolerance

Taxons: error-resilience

HTML version: https://auditbuffet.com/patterns/ab-002287
