React Router v6 changed how we handle navigation, data loading, and error handling in React apps. With its new Data Router API, you can now catch and handle errors at the route level — but wiring that into your error monitoring requires a deliberate strategy. If you're using Sentry or a Sentry-compatible service like LightTrace, you need to know how to surface route-level errors, catch boundaries that actually matter, and wire server-side errors from loaders and actions into your error tracking.
This guide covers everything: client-side error boundaries that work with React Router v6, server-side error capture in Data Router mode, and integration with a monitoring service so you see every error that matters in one place.
Why React Router v6 Error Monitoring Reporting Matters
React Router v6 introduced a new mental model: loaders run before components render, actions handle mutations, and errors can originate either in the UI tree or in the routing layer. A loader that throws during data fetching never reaches the component. An action that fails in the middle of a form submission behaves differently than a client-side render error. A standard client-side error monitoring setup won't catch loader and action failures unless you explicitly propagate them.
Without proper wiring, you'll miss critical errors — incomplete data loads, auth token expiration during actions, failed database queries in loaders. Your users see a blank page or a generic error fallback; you see nothing.
Setting Up Sentry SDK with LightTrace
Start by installing the Sentry SDK for React. LightTrace is Sentry-compatible, so you use the same SDK; you only change the DSN.
npm install @sentry/react @sentry/tracing
Initialize Sentry early in your app entry point, before your router renders:
import React from 'react'
import ReactDOM from 'react-dom/client'
import * as Sentry from '@sentry/react'
import { BrowserTracing } from '@sentry/tracing'
import App from './App'
Sentry.init({
dsn: 'https://<your-key>@light-trace.robomiri.com/1',
integrations: [
new BrowserTracing(),
],
tracesSampleRate: 0.1, // Adjust based on traffic
environment: process.env.NODE_ENV,
})
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
Replace <your-key> and light-trace.robomiri.com with your LightTrace project credentials. The BrowserTracing integration automatically captures navigation events and network requests as spans, giving you distributed tracing context for each error.
Set tracesSampleRate conservatively in production — capture 5–10% of transactions to stay within event budgets while keeping your error rate data representative.
Client-Side Error Boundaries
React Router v6 still uses the classic error boundary pattern for UI errors. Wrap your route tree in a Sentry error boundary:
import { RouterProvider, createBrowserRouter } from 'react-router-dom'
import * as Sentry from '@sentry/react'
const SentryRoutes = Sentry.withSentryRouting(RouterProvider)
const router = createBrowserRouter([
{
path: '/',
element: <Home />,
errorElement: <ErrorBoundary />,
},
{
path: '/dashboard',
element: <Dashboard />,
errorElement: <ErrorBoundary />,
},
])
function App() {
return <SentryRoutes router={router} />
}
The errorElement prop tells React Router what to render if a component throws. Create a reusable error boundary component:
import { useRouteError } from 'react-router-dom'
import * as Sentry from '@sentry/react'
export function ErrorBoundary() {
const error = useRouteError()
Sentry.captureException(error, {
tags: {
'error.type': 'react-router-boundary',
},
})
if (error.status === 404) {
return <div>Page not found</div>
}
return (
<div>
<h1>Something went wrong</h1>
<p>{error.message || 'An unexpected error occurred'}</p>
</div>
)
}
Using useRouteError() gives you access to the thrown error or a Response object. Capture it to Sentry immediately — don't rely on global handlers to catch it, because the error is already being handled by the error boundary.
Server-Side Error Capture in Data Router Mode
Data Router (also called "future-ready" mode) is where React Router really shines — and where error monitoring becomes crucial. Loaders and actions run on the server or client before the component renders. If a loader fails to fetch data, the route's errorElement displays, but the error might not reach your monitoring.
Wrap your loader and action functions explicitly:
import * as Sentry from '@sentry/react'
const loader = async ({ params }) => {
try {
const response = await fetch(`/api/user/${params.id}`)
if (!response.ok) throw new Error(`User ${params.id} not found`)
return response.json()
} catch (error) {
Sentry.captureException(error, {
tags: {
'error.source': 'loader',
'route': `/user/${params.id}`,
},
})
throw error
}
}
Similarly, for actions (form submissions, mutations):
const updateUserAction = async ({ request, params }) => {
if (request.method !== 'POST') {
throw new Response('Method not allowed', { status: 405 })
}
try {
const formData = await request.formData()
const response = await fetch(`/api/user/${params.id}`, {
method: 'POST',
body: JSON.stringify(Object.fromEntries(formData)),
})
if (!response.ok) {
throw new Error('Failed to update user')
}
return response.json()
} catch (error) {
Sentry.captureException(error, {
tags: {
'error.source': 'action',
'action.type': 'updateUser',
},
})
throw error
}
}
By tagging errors with their source, you can later filter in LightTrace to see loader failures vs. action failures vs. component crashes. This context is essential for debugging production issues.
If you're using React Server Components or SSR, initialize Sentry on your server separately with the Node SDK. Loader and action errors on the server are caught by your server-side error handler, not the browser SDK.
Route-Level Error Context
Adding route metadata to every error helps you correlate issues with specific workflows. Leverage Sentry's scope API to attach route context automatically:
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import * as Sentry from '@sentry/react'
export function RouteErrorContext() {
const location = useLocation()
useEffect(() => {
Sentry.setTag('route', location.pathname)
Sentry.setContext('navigation', {
pathname: location.pathname,
search: location.search,
})
}, [location])
return null
}
Render this component once at the app root:
function App() {
return (
<>
<RouteErrorContext />
<SentryRoutes router={router} />
</>
)
}
Now every error captured in your app will include the current route and query parameters. In LightTrace, you can group issues by route, see which endpoints cause the most errors, and investigate specific user journeys.
Debugging & Alerts in Production
Once you've instrumented your application, errors from loaders, actions, and React components flow into LightTrace. Set up alert rules to notify you of critical issues:
- New Issue: Alert when an entirely new error type appears — often a sign of a bad deploy.
- Event Frequency: Alert when a known issue exceeds a threshold (e.g., 10 errors in 1 hour).
Configure these in LightTrace's alert settings; emails are delivered instantly. Use tags and contexts to make your alerts smart: alert only on production errors, or only on errors affecting a specific user segment.
For debugging, use LightTrace's source-map integration to get decompiled stack traces and click straight to the offending line on GitHub. Breadcrumbs show you exactly which router transitions, fetch calls, and user actions led up to the error.
Never log sensitive user data (passwords, tokens, PII) in error messages or breadcrumbs. LightTrace's scrubbing rules can redact common patterns, but explicit data masking in your error handlers is safer.
Testing Error Paths
Before deploying error handling, test it. Simulate loader failures in development:
const testLoader = async ({ params }) => {
if (process.env.NODE_ENV === 'development' && params.id === 'error') {
throw new Error('Test error from loader')
}
// normal loader logic
}
Visit /user/error in dev mode and check that your error boundary renders and the error is captured. Use LightTrace's test integration or curl request to verify your DSN works:
curl -X POST https://<your-key>@light-trace.robomiri.com/1 \
-H "Content-Type: application/json" \
-d '{"message":"Test event"}'
Wrapping Up
React Router v6 gives you powerful control over routing errors, but only if you wire them into your monitoring. Client-side error boundaries are a start, but loaders and actions are where real data failures hide. By explicitly capturing errors in both layers, tagging them with route context, and watching alerts in LightTrace, you'll catch routing issues before your users report them.
For a deeper dive on error tracking fundamentals, or if you're interested in how this fits into broader instrumentation strategies, check those guides. And if you're coming from another framework, we have guides for Vue and Next.js as well.
Start tracking errors in minutes
Start free with LightTrace and get your React Router v6 errors monitored in under 5 minutes. No credit card required.