Skip to content

Add error.tsx and not-found.tsx to root and key route segments #49

@studert

Description

@studert

Problem

Next.js App Router supports per-segment error.tsx and not-found.tsx files that gracefully render a UI when a server component throws or a route doesn't match. The repo currently has none — every uncaught server error renders the framework's default error screen, and any unknown route falls back to the framework's default 404. This is jarring for users and makes incident triage harder because there's no opportunity to log a correlation id or render a friendly retry CTA.

Evidence

  • A repo-wide search for error.tsx, not-found.tsx returns no matches under src/app/.
  • All segments rely on Next's defaults.

Proposed approach

  1. Create src/app/error.tsx (root error boundary):

    • \"use client\" per Next.js docs.
    • Receives { error, reset } props.
    • Logs error.digest and error.message via the structured logger (or console.error for now).
    • Renders a shadcn/ui Card with title "Something went wrong", body containing error.digest (collapsed), and a button calling reset().
  2. Create src/app/not-found.tsx:

    • Renders a shadcn/ui card with "Page not found" + a Link back to /.
  3. Create segment-level error.tsx for each major route group, reusing a shared ErrorState component to keep them DRY:

    • src/app/assignments/error.tsx
    • src/app/budget/error.tsx
    • src/app/invoices/error.tsx
    • src/app/copilot/error.tsx
    • src/app/claude/error.tsx
    • src/app/reports/error.tsx
    • src/app/settings/error.tsx
  4. Extract the shared component to src/components/error-state.tsx so per-segment files are 5–10 lines.

  5. Make sure the error boundary preserves the sidebar layout — wrap ErrorState so it renders inside the existing <AppShell> rather than full-page.

  6. Add a Playwright smoke test (1 spec, 2 cases) that:

    • Navigates to /__nope__ and asserts the not-found UI renders.
    • (Optional) hits a route segment with a deliberately throwing dev-only flag and asserts the error UI renders.

Acceptance criteria

  • Root error.tsx and not-found.tsx exist and render the shared component.
  • At least 5 segment-level error.tsx files cover the major route groups listed above.
  • Shared ErrorState component is reused everywhere — no copy-pasted JSX.
  • Visiting a non-existent path renders the new 404 UI inside the app layout.
  • pnpm lint && pnpm typecheck pass.

Verification

  1. pnpm dev, navigate to http://localhost:3000/__nope__ → expect the new 404 UI.
  2. Temporarily throw new Error(\"boom\") at the top of any server component (e.g. src/app/copilot/page.tsx) → expect the segment error UI with a Try Again button. Revert.
  3. Click "Try Again" → page re-renders without a hard reload.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority:mediumImportant, not urgenttech-debtCode quality, refactor, debt

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions