From dc313dc50a7b797df77805f6d72e4134a6aefe78 Mon Sep 17 00:00:00 2001 From: Codex Review Integration Date: Thu, 3 Sep 2026 15:53:50 -0300 Subject: [PATCH] fix: capture React root errors in Sentry --- docs/adr/0002-sentry-observability.md | 5 ++++- src/main.tsx | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/adr/0002-sentry-observability.md b/docs/adr/0002-sentry-observability.md index 02c0b549..fc6bce5f 100644 --- a/docs/adr/0002-sentry-observability.md +++ b/docs/adr/0002-sentry-observability.md @@ -18,7 +18,10 @@ Use the pinned `@sentry/react` 10.73.0 SDK. Initialize it before the application router is created, and wrap `createBrowserRouter` with Sentry's current React Router compatibility API. Configure the browser tracing integration with a 100% transaction sample rate, and propagate trace headers only to the SPA origin and -the configured `VITE_API_URL` base. +the configured `VITE_API_URL` base. Pass `Sentry.reactErrorHandler()` as the +`onCaughtError`, `onUncaughtError`, and `onRecoverableError` callbacks of +`ReactDOM.createRoot`, so React 19's root error hooks capture caught, uncaught, +and recoverable component errors as Sentry events. The DSN comes from `VITE_SENTRY_DSN`. It is intentionally treated as public browser configuration because every `VITE_` value is embedded in the built diff --git a/src/main.tsx b/src/main.tsx index deebc060..4e683029 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,3 +1,5 @@ +import * as Sentry from "@sentry/react"; + import "@/observability/sentry"; import React from "react"; @@ -12,7 +14,11 @@ if (!rootElement) { throw new Error("Root element #root not found"); } -ReactDOM.createRoot(rootElement).render( +ReactDOM.createRoot(rootElement, { + onCaughtError: Sentry.reactErrorHandler(), + onRecoverableError: Sentry.reactErrorHandler(), + onUncaughtError: Sentry.reactErrorHandler(), +}).render(