import * as React from "react"; import { Link, useRouter } from "@tanstack/react-router"; import type { ErrorComponentProps } from "@tanstack/react-router"; import { ERROR_COPY, errorKind, type ErrorKind } from "~/lib/error-copy"; import { HttpError } from "~/server/errors"; import { captureException } from "~/lib/analytics"; import { Button, buttonClass } from "~/ui/Button"; import { ErrorScreen } from "~/ui/ErrorScreen"; const INTERNAL = 500; const RETRYABLE: ReadonlySet = new Set(["server", "unavailable", "rate-limited"]); /** HttpErrors carry user-facing messages; anything else may leak internals, so only show it in dev. */ function errorDetail(error: unknown): string | null { if (error instanceof HttpError) return error.message; if (import.meta.env.DEV && error instanceof Error) return error.message; return null; } function PrimaryAction({ kind, onRetry }: { kind: ErrorKind; onRetry: () => void }) { if (kind === "unauthorized") { return ( Sign in ); } if (!RETRYABLE.has(kind)) return null; return ( ); } export function DefaultCatchBoundary({ error, reset }: ErrorComponentProps) { const router = useRouter(); console.error("Route error:", error); React.useEffect(() => { if (!(error instanceof HttpError)) captureException(error); }, [error]); const status = error instanceof HttpError ? error.status : INTERNAL; const kind = errorKind(status); const copy = ERROR_COPY[kind]; const hasPrimary = kind === "unauthorized" || RETRYABLE.has(kind); async function retry() { reset(); await router.invalidate(); } return ( void retry()} /> Take me home } /> ); }