Documentation

Crash Reports

Configure crash reporting to detect when browser tabs crash, run out of memory, or become unresponsive — failures that destroy your JavaScript environment before any error handler can run.

New to crash reporting? Read our Crash Reports overview to understand the benefits before diving into configuration.

What are Crash Reports?

Crash reports are notifications that browsers send when a tab or page fails catastrophically. Unlike JavaScript errors (which your error tracking SDK can catch), crashes destroy the entire JavaScript environment — no window.onerror, no unhandledrejection, no SDK can run code that no longer exists.

When a tab crashes, the browser itself generates a report and delivers it out-of-band — typically on the next successful page load, or even from a different tab. This is the only way to get evidence that a user's session ended in failure rather than by choice.

Each crash report includes a reason field indicating what type of crash occurred (like oom for out-of-memory or unresponsive for killed tabs), along with metadata about the document's visibility state at crash time.

Specification

Browser Support

Crash reporting is supported in Chromium-based browsers starting from version 96 (October 2021). Firefox and Safari do not currently support crash reporting.

Browser Support Notes
Chrome 96+ Full support
Edge 96+ Full support
Opera 82+ Full support
Firefox Not supported
Safari Not supported
Chromium-only feature: Crash reporting is only available in Chromium-based browsers (Chrome, Edge, Opera). Reports will not come from Firefox or Safari users.

Why Monitor Crash Reports?

Crash reports reveal failures that are completely invisible to traditional monitoring:

  • The blind spot in error tracking — Your JavaScript error SDK can't report crashes because it's destroyed along with everything else. Crash reports survive because the browser itself sends them.
  • Silent user churn — Users who experience crashes often just leave. They don't report the issue — they assume something's wrong on their end or simply give up. You see a session end but have no idea it ended in failure.
  • SPA memory pressure — Single-page applications are especially vulnerable. Heavy state management, data visualization, and long sessions can push against browser memory limits (typically ~2GB per tab on desktop).
  • Release correlation — Correlate crash spikes with deployments to identify stability regressions before they affect more users.
  • Production-only visibility — Memory leaks and performance issues often only manifest in production with real user data and session lengths that local testing doesn't replicate.

Who Benefits

  • SRE teams — Monitor application stability and correlate crashes with releases
  • Frontend architects — Identify memory-intensive features that push browsers to their limits
  • Product managers — Understand when user sessions end due to crashes vs. normal abandonment
  • Performance engineers — Track unresponsive tab kills alongside performance metrics

When to Enable

Crash reporting is recommended for all production websites, but it's essential for applications with these characteristics:

  • Single-page applications (SPAs) — Long-running sessions accumulate memory
  • Data-heavy dashboards — Large datasets and visualizations stress memory limits
  • Collaborative editors — Real-time sync and undo history consume memory
  • Media applications — Video editing, image processing, and WebGL push GPU and memory

The report volume is typically low (crashes are relatively rare events), but each report represents a user who had a seriously degraded experience.

How to Configure

Automatic reporting: Crash reports are sent automatically to your crash-reporting endpoint if defined, or your default endpoint otherwise. There's no additional header to configure beyond Reporting-Endpoints.

Step 1: Set Up the Reporting Endpoint

Define where browsers should send crash reports using the Reporting-Endpoints header:

HTTP Define the reporting endpoint
Reporting-Endpoints: default="https://reporting-api.app/browser-reports/YOUR-ENDPOINT-UUID"

Replace YOUR-ENDPOINT-UUID with your application's unique endpoint from the Reporting API App dashboard.

Optional: Dedicated Crash Endpoint

If you want crash reports to go to a different endpoint than other report types, you can define a dedicated crash-reporting endpoint:

HTTP Separate endpoint for crashes (optional)
Reporting-Endpoints: default="https://reporting-api.app/browser-reports/YOUR-UUID", crash-reporting="https://reporting-api.app/browser-reports/YOUR-CRASH-UUID"

Crash reports will be sent to crash-reporting if defined, otherwise to default.

Step 2: That's It!

There's no additional configuration required. Once the Reporting-Endpoints header is in place, browsers will automatically send crash reports when tabs crash, run out of memory, or become unresponsive.

Why so simple? Crash reporting is automatic — you can't opt into specific crash types or set thresholds. The browser decides when a crash occurs and reports it. Your only configuration is where to send the reports.

Step 3: Monitor Reports

After deploying the header, crash reports will flow in when crashes occur. Monitor incoming reports for:

  • OOM crashes — Out-of-memory failures indicating memory leaks or excessive usage
  • Unresponsive crashes — Tabs killed due to being unresponsive (infinite loops, heavy computation)
  • Crash rate trends — Spikes after deployments may indicate stability regressions

Step 4: Set Up Integrations

Route crash reports to your existing tools for alerting and analysis:

See the Integrations documentation for setup instructions.

Understanding Crash Reports

When a browser crashes, it generates a JSON report explaining what happened. Understanding these fields helps you investigate and address the root cause.

Report Fields

Field Description
reason Classification of the crash type: oom (out-of-memory) or unresponsive (tab killed). May be omitted if unknown.
stack JavaScript call stack at crash time (only for unresponsive crashes when enabled via Document-Policy). Same format as Error.prototype.stack.
is_top_level Boolean indicating whether the crashed document was the top-level page (true) or an iframe (false).
visibility_state Document visibility at crash time: visible or hidden. Helps distinguish active vs. background tab crashes.

Example Report

JSON Crash report (out-of-memory)
{
  "type": "crash",
  "age": 42,
  "url": "https://example.com/dashboard",
  "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  "body": {
    "reason": "oom"
  }
}
JSON Crash report (unresponsive with stack trace)
{
  "type": "crash",
  "age": 0,
  "url": "https://example.com/editor",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
  "body": {
    "reason": "unresponsive",
    "stack": "    at processData (https://example.com/js/app.js:1234:56)\n    at updateView (https://example.com/js/app.js:789:12)"
  }
}

Crash Types

Browsers report two standardized crash reasons:

Reason Cause Common Triggers
oom Page ran out of memory Memory leaks, large data structures, canvas/WebGL, unbounded caches
unresponsive Tab killed due to being unresponsive Infinite loops, blocking operations, heavy computation on main thread

Out-of-Memory (OOM) Crashes

OOM crashes occur when your application exceeds the browser's per-tab memory limit (typically around 2GB on desktop, less on mobile). Research shows:

  • OOM errors account for roughly 10% of all browser crashes
  • Studies of popular SPAs found that 10 out of 10 had memory leaks
  • Memory issues often only manifest with real user data and session lengths

Common causes include:

  • Memory leaks — DOM nodes retained after removal, closure scope leaks, event listener accumulation
  • Large data structures — Unbounded arrays, large object graphs, excessive caching
  • Canvas and WebGL — High-resolution images, video frames, 3D rendering
  • Growing undo history — Collaborative editors storing every change

Unresponsive Tab Crashes

Unresponsive crashes occur when the browser kills a tab that hasn't responded for too long. The browser protects users from pages that freeze their computer.

Common causes include:

  • Infinite loopswhile(true) or recursive calls without base cases
  • Synchronous heavy computation — Parsing large JSON, complex algorithms on main thread
  • Blocking I/O — Synchronous XHR (deprecated but still used in legacy code)
  • Deadlocks — Waiting for resources that will never become available
Stack traces for unresponsive crashes: For unresponsive crashes, you can enable JavaScript call stack capture by adding the Document-Policy: include-js-call-stacks-in-crash-reports header. This provides visibility into exactly where the code was stuck.

Enabling Stack Traces

By default, crash reports don't include JavaScript stack traces. For unresponsive crashes, you can enable stack capture using the Document-Policy header:

HTTP Enable stack traces in crash reports
Document-Policy: include-js-call-stacks-in-crash-reports
Reporting-Endpoints: default="https://reporting-api.app/browser-reports/YOUR-UUID"

When enabled, unresponsive crash reports will include a stack field with the JavaScript call stack at the time the page became unresponsive. The format matches Error.prototype.stack and respects Error.stackTraceLimit.

Only for unresponsive crashes: Stack traces are only available for unresponsive crashes. OOM crashes destroy the JavaScript heap before a stack can be captured — there's no call stack to report.

Testing Crash Reports

To verify your crash reporting configuration, you can trigger test crashes in Chrome using special URLs:

Chrome URL Effect
chrome://crash/ Simulates a generic browser crash
chrome://memory-exhaust/ Triggers an out-of-memory (oom) crash
chrome://hang/ Makes the tab unresponsive (wait for browser to kill it)
Asynchronous delivery: Crash reports are delivered asynchronously — not immediately after the crash. They're queued and sent on the next successful page load or from another tab. Check your dashboard after triggering a test crash; it may take a few moments for the report to appear.

You can also test with the interactive Reporting API Crash Demo.

Preventing Crashes

While crash reports help you detect problems, prevention is better than detection:

Preventing OOM Crashes

  • Profile memory regularly — Use Chrome DevTools Memory panel to identify leaks
  • Limit cache sizes — Set maximum sizes for in-memory caches and implement LRU eviction
  • Clean up references — Remove event listeners, clear intervals, null-out large objects
  • Stream large data — Process data in chunks rather than loading everything at once
  • Monitor in production — Use performance.memory (Chrome-only) to track heap usage

Preventing Unresponsive Crashes

  • Use Web Workers — Move heavy computation off the main thread
  • Chunk long operations — Break work into smaller pieces with requestIdleCallback
  • Avoid synchronous APIs — Never use sync XHR or other blocking operations
  • Add safety limits — Use iteration limits and timeouts for loops and recursion

Server Configuration Examples

Nginx

Nginx nginx.conf
server {
    # ... your existing configuration ...

    # Reporting endpoint for all report types including crashes
    add_header Reporting-Endpoints 'default="https://reporting-api.app/browser-reports/YOUR-UUID"' always;

    # Optional: Enable stack traces for unresponsive crashes
    add_header Document-Policy 'include-js-call-stacks-in-crash-reports' always;
}

Ruby on Rails

Ruby config/application.rb or initializer
# Add Reporting-Endpoints header for crash and other reports
# Note: Use lowercase header names for Rack 3 compatibility
config.action_dispatch.default_headers.merge!(
  "reporting-endpoints" => 'default="https://reporting-api.app/browser-reports/YOUR-UUID"',
  # Optional: Enable stack traces for unresponsive crashes
  "document-policy" => "include-js-call-stacks-in-crash-reports"
)

Apache

Apache .htaccess or httpd.conf
Header always set Reporting-Endpoints 'default="https://reporting-api.app/browser-reports/YOUR-UUID"'
# Optional: Enable stack traces for unresponsive crashes
Header always set Document-Policy 'include-js-call-stacks-in-crash-reports'

Troubleshooting

Reports Not Appearing

  • Check browser support — Crash reports only work in Chrome 96+, Edge 96+, and other Chromium browsers. Firefox and Safari do not support this feature.
  • Verify headers are sent — Use browser DevTools (Network tab) to confirm the Reporting-Endpoints header is present in responses.
  • Check allowed origins — Ensure your website's origin is whitelisted in your application settings.
  • Wait for delivery — Crash reports are delivered asynchronously, often on the next page load. They won't appear immediately.
  • Trigger a test crash — Use chrome://crash/ or chrome://memory-exhaust/ to generate a test report.

Missing Stack Traces

  • Check Document-Policy header — Stack traces require Document-Policy: include-js-call-stacks-in-crash-reports.
  • Only unresponsive crashes — Stack traces are only included for unresponsive crashes, not OOM.
  • Minified code — Use source maps in your error tracking tools to make stack traces readable.

Distinguishing Real Crashes from Test Data

  • Filter by URL — Test crashes from chrome:// URLs have different URL patterns.
  • Use staging environments — Test in staging before production deployment.
  • Check user agent — Your test browser's user agent will be identifiable in reports.

Next Steps