import { isRouteErrorResponse, useNavigate, useRouteError } from "react-router" import { AlertTriangle, RefreshCw, Home } from "lucide-react" import { AppShell } from "~/components/layout/app-shell" import { Button } from "~/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card" /** * Route-level error boundary. * * Re-export this as `ErrorBoundary` from any route and a crash in that route * degrades to a single explained card *inside the shell* — the nav, the theme * and every other screen stay reachable. The root boundary in `root.tsx` still * exists as the last resort, but it replaces the whole app with an unstyled * stack trace, which strands an operator mid-incident with no way out. * * export { RouteErrorBoundary as ErrorBoundary } from "~/components/route-error" */ export function RouteErrorBoundary() { const error = useRouteError() const navigate = useNavigate() let title = "This screen hit an error" let description = "Something on this page failed to render. The rest of the console still works — you can retry, or head back to the overview." if (isRouteErrorResponse(error)) { if (error.status === 404) { title = "That page doesn't exist" description = "The link may be stale, or the screen may have been renamed." } else { title = `Request failed (${error.status})` description = error.statusText || "The server rejected this request. Retry, and if it keeps failing check the service logs." } } // The message is useful to an operator even in prod — it's their own platform. // The stack is noise unless you're the one fixing it, so it stays in dev. const message = error instanceof Error ? error.message : null const stack = import.meta.env.DEV && error instanceof Error ? error.stack : undefined return (
{title} {description}
{message ? (

{message}

) : null}
{stack ? (
Stack trace (dev only)
                {stack}
              
) : null}
) }