new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

React Router · Guides · all subjects

error-handling

16 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

ErrorBoundary catches route errors but doesn't log them

React Router catches errors in route modules and sends them to error boundaries to prevent blank pages. However, ErrorBoundary is not sufficient for logging and reporting errors—you need additional error handlers.

Server error reporting with handleError export

To access caught errors on the server, export a handleError function from the server entry module. This function is called whenever React Router catches an error in your application on the server. The function receives an error object and a context object containing the request. You should check if request.signal.aborted is false before logging, as React Router may abort some interrupted requests.

Server handleError function signature and example

The handleError function has type HandleErrorFunction and receives an error parameter and a context object with a request property. Example implementation: import { type HandleErrorFunction } from "react-router"; export const handleError: HandleErrorFunction = ( error, { request }, ) => { if (!request.signal.aborted) { myReportError(error); console.error(error); } };

Client error reporting with onError prop

To access caught errors on the client, use the onError prop on either HydratedRouter (framework mode) or RouterProvider (data mode) component. This function is called whenever React Router catches an error in your application on the client.

Reveal client entry module with CLI

If you don't see entry.client.tsx in your app directory, you're using a default entry. Reveal it with the command: react-router reveal entry.client

Framework mode client onError function signature and example

In framework mode, the onError function has type ClientOnErrorFunction and receives an error parameter and a context object with location, params, pattern, and errorInfo properties. Example implementation: import { type ClientOnErrorFunction } from "react-router"; const onError: ClientOnErrorFunction = ( error, { location, params, pattern, errorInfo }, ) => { myReportError(error, location, errorInfo); console.error(error, errorInfo); }; startTransition(() => { hydrateRoot( document, <StrictMode> <HydratedRouter onError={onError} /> </StrictMode>, ); });

Data mode client onError function signature and example

In data mode, the onError function has type ClientOnErrorFunction and receives an error parameter and a context object with location, params, pattern, and errorInfo properties. Example implementation: import { createBrowserRouter, type ClientOnErrorFunction, } from "react-router"; import { RouterProvider } from "react-router/dom"; const onError: ClientOnErrorFunction = ( error, { location, params, pattern, errorInfo }, ) => { myReportError(error, location, errorInfo); console.error(error, errorInfo); }; const router = createBrowserRouter(routes); function App() { return ( <RouterProvider router={router} onError={onError} /> ); }

Catch-all route should return 404 status

By default a catch-all route returns a 200 response. Modify your $.tsx catch-all route to return a 404 status. For example: export async function loader() { return data({}, 404); }

Instrumentation error handling with discriminated union result

When a handler function (loader, action, request handler, navigation, etc.) throws an error, that error will not bubble out of the callHandler function invoked from your instrumentation. Instead, the callHandler function returns a discriminated union result of type { status: 'success', error: undefined } | { status: 'error', error: Error }. This ensures your entire instrumentation function runs without needing try/catch/finally logic to handle application errors. Check the status property to determine if the handler succeeded or failed.

Instrumentation errors are gracefully swallowed

If your instrumentation function throws an error, React Router will gracefully swallow that error so it does not bubble outward and impact other instrumentations or application behavior. Errors thrown before calling the handler, after calling the handler, or within the handler will all be caught internally. All handlers and other instrumentation functions will still run.

Middleware error handling with ErrorBoundary

When middleware throws an error, it is caught and handled at the appropriate ErrorBoundary and a Response is returned through the ancestor next() call. The next() function should never throw and should always return a Response. Errors thrown after calling next() bubble up from the throwing route like normal loader errors. Errors thrown before calling next() bubble up to the highest route with a loader because no loaders have run yet and no loaderData is available.

Resource route error handling with thrown errors

Throwing an Error (or anything other than a Response or data()) from a resource route triggers handleError and results in a 500 HTTP response.

Resource route error handling with Response objects

When a resource route generates a Response (via new Response() or data()), it is considered successful execution and will not trigger handleError, even with 4xx/5xx status codes. Thrown Response objects, returned Response objects with error status codes, and data() calls with error status are all equivalent and do not trigger handleError. This aligns with fetch() behavior which does not reject on 4xx/5xx responses.

Error boundaries in resource routes

Error boundaries apply only when a resource route is accessed from a UI, such as from a fetcher call or Form submission. If you throw from a resource route in these cases, it will bubble to the nearest ErrorBoundary in the UI.

Throw data() for error status codes

To send error status codes like 404 from a loader or action, throw the `data` function result instead of returning it. For example: `throw data('Not Found', { status: 404 })` will throw to the ErrorBoundary with a 404 status code.

Register process-level unhandledRejection handler in server entry

To prevent process crashes from early promise rejections in Node, register a process-level unhandledRejection handler in entry.server.ts: ```ts process.on("unhandledRejection", (reason, promise) => { console.error( "Unhandled Rejection at:", promise, "reason:", reason, ); }); ```

Give your agent this brain