# window.onerror handler catches synchronous errors

- **Pattern:** `ab-001281` (`error-resilience.logging-observability.window-onerror-handler`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001281
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001281)

## Why it matters

Third-party scripts — analytics, chat widgets, A/B testing tools — run in the same JavaScript context as your application. A synchronous error in any of them crashes the page if `window.onerror` is not configured. CWE-703 applies: failures in external code are exceptional conditions your app must handle. Without this handler, you have no visibility into crashes caused by vendor script updates, and users experience blank pages with no error surface in your error tracking dashboard.

## Severity rationale

High because synchronous errors from third-party scripts silently crash the page with no diagnostic trail unless a global handler is in place.

## Remediation

Register `window.onerror` early in your app's entry point or layout. Return `true` to suppress the default browser error dialog.

```ts
// app/layout.tsx or lib/error-handlers.ts (client-side only)
if (typeof window !== 'undefined') {
  window.onerror = (message, source, lineno, colno, error) => {
    reportError(error ?? new Error(String(message)), {
      source,
      lineno,
      colno,
    })
    return true // suppress browser console error
  }
}
```

Pair with `unhandledrejection` handler (see `unhandled-promise-rejection`) for full client-side coverage. The handler must forward to your error tracking service, not just `console.error`.

## Detection

- **ID:** `window-onerror-handler`
- **Severity:** `high`
- **What to look for:** Count all global error handler registrations (window.onerror, window.addEventListener("error")). Enumerate whether uncaught exceptions are captured and reported. Search for `window.onerror` configuration in client-side code. This handler should catch synchronous errors from third-party scripts and prevent a blank screen.
- **Pass criteria:** A `window.onerror` handler is configured that captures synchronous errors and logs them to an error tracking service. At least 1 global error handler must be registered for uncaught exceptions.
- **Fail criteria:** No `window.onerror` handler found, or handler exists but does not log to an error tracking service.
- **Skip (N/A) when:** The application has no client-side JavaScript or no external scripts.

- **Cross-reference:** For unhandled promise rejections, see `unhandled-promise-rejection`. For error tracking service, see `error-tracking-service`.
- **Detail on fail:** `"No window.onerror handler configured. Synchronous errors from third-party scripts will crash the page"` or `"Handler exists but only logs to console, not to error tracking"`
- **Remediation:** Configure a global error handler in your app's entry point:

  ```ts
  // lib/error-handlers.ts — global error handler
  if (typeof window !== 'undefined') {
    window.onerror = (msg, src, line, col, err) => { reportError(err || new Error(String(msg))) }
  }
  ```

  ```ts
  // app/layout.tsx or index.tsx
  if (typeof window !== 'undefined') {
    window.onerror = (message, source, lineno, colno, error) => {
      console.error('Global error:', { message, source, lineno, colno, error })
      // Send to error tracking service
      Sentry.captureException(error || new Error(message))
      return true // Prevent default handling
    }
  }
  ```

## External references

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

Taxons: error-resilience, observability

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