Next.js cookbook · Beginner

Handle errors and 404s in the App Router

Show friendly error pages per section, recover with a retry, and return real 404s for missing records.

Approach

Add error.tsx (a Client Component boundary) in route segments to catch rendering errors with a reset() retry, global-error.tsx for root-layout failures, and call notFound() when data doesn't exist so not-found.tsx renders with a 404 status. Log errors to your monitoring tool.

Solution

// app/projects/[id]/page.tsx
import { notFound } from "next/navigation";
export default async function ProjectPage({ params }: { params: Promise<{ id: string }> }) {
  const project = await getProject((await params).id);
  if (!project) notFound();
  return <ProjectView project={project} />;
}

// app/projects/[id]/not-found.tsx
export default function NotFound() {
  return <div><h2>Project not found</h2><a href="/projects">Back to projects</a></div>;
}

// app/projects/error.tsx
"use client";
import { useEffect } from "react";
export default function ProjectsError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
  useEffect(() => { reportError(error); }, [error]);
  return (
    <div role="alert">
      <h2>Something went wrong loading projects.</h2>
      <p>Reference: {error.digest}</p>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

Pitfalls

  • error.tsx without "use client".
  • Rendering an empty page instead of notFound() (soft 404s hurt SEO).
  • Exposing server error messages — production errors are sanitized; use the digest to correlate logs.

Variations

  • instrumentation.ts onRequestError hook to report server errors centrally.

Further reading: Next.js: Error handling

Reference: https://nextjs.org/docs/app/getting-started/error-handling

More Next.js recipes