# add-error-boundary > Add error boundaries to routes for handling 404s, 403s, and unexpected errors. Use when implementing error handling for routes or when asked to handle not found pages. - Author: Seth Davis - Repository: tech-with-seth/iridium - Version: 20260119233733 - Stars: 1 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/tech-with-seth/iridium - Web: https://mule.run/skillshub/@@tech-with-seth/iridium~add-error-boundary:20260119233733 --- --- name: add-error-boundary description: Add error boundaries to routes for handling 404s, 403s, and unexpected errors. Use when implementing error handling for routes or when asked to handle not found pages. --- # Add Error Boundary Adds React Router 7 error boundaries to routes for graceful error handling, preventing blank pages for users. ## When to Use - Adding 404 handling for missing resources - Adding 403 handling for unauthorized access - Creating custom error pages for specific routes - User asks to "add error handling" or "handle not found" ## Critical Patterns ### 1. Route Error Boundary Export ```tsx import type { Route } from './+types/my-route'; import { isRouteErrorResponse, Link } from 'react-router'; export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) { // 1. Handle intentional HTTP errors (404, 403, etc.) if (isRouteErrorResponse(error)) { if (error.status === 404) { return (

Not Found

{error.data}

Go Home
); } if (error.status === 403) { return (

Access Denied

You don't have permission to view this.

); } return (

{error.status} {error.statusText}

{error.data}

); } // 2. Handle JavaScript errors if (error instanceof Error) { return (

Error

{error.message}

{process.env.NODE_ENV === 'development' && (
                        {error.stack}
                    
)}
); } // 3. Unknown errors return

Unknown Error

; } ``` ### 2. Throwing 404s in Loaders ```tsx import type { Route } from './+types/product'; import { data } from 'react-router'; import { getProduct } from '~/models/product.server'; export async function loader({ params }: Route.LoaderArgs) { const product = await getProduct(params.id); if (!product) { throw data('Product not found', { status: 404 }); } return { product }; } ``` ### 3. Throwing 403s for Authorization ```tsx import type { Route } from './+types/resource'; import { data } from 'react-router'; import { requireUser } from '~/lib/session.server'; import { getResource } from '~/models/resource.server'; export async function loader({ request, params }: Route.LoaderArgs) { const user = await requireUser(request); const resource = await getResource(params.id); if (!resource) { throw data('Resource not found', { status: 404 }); } if (resource.userId !== user.id && user.role !== 'ADMIN') { throw data('Unauthorized', { status: 403 }); } return { resource }; } ``` ## Error Boundary Placement | Error Source | Boundary Used | |-------------|---------------| | Root layout | `app/root.tsx` ErrorBoundary | | Child route without boundary | Bubbles to parent | | Route with own ErrorBoundary | Uses own ErrorBoundary | **Most errors should bubble to root.** Only add route-specific boundaries when custom UX is needed. ## When to Use `throw data()` - 404s when records don't exist - 403s for unauthorized access - 410s for deleted resources ## When NOT to Use Error Boundaries - Form validation errors (use action error responses) - Expected business logic (use normal returns) - General control flow ## Anti-Patterns - Using error boundaries for form validation - Throwing `new Error()` for control flow (use `throw data()` with status) - Adding ErrorBoundary to every route (over-engineering) - Exposing stack traces in production - Using `throw data()` for general control flow ## Root ErrorBoundary Required Every app needs an ErrorBoundary in `app/root.tsx` - check it exists before adding route-specific ones. ## Full Reference See `.github/instructions/error-boundaries.instructions.md` for comprehensive documentation.