Skip to content

Error Pages

Next.js provides two dedicated conventions for handling failure states: error.tsx for runtime errors thrown during rendering, and not-found.tsx for missing content. This lesson covers both, along with global error handling.

error.tsx: Automatic Error Boundaries

Adding an error.tsx file to a route folder automatically wraps that segment's content in a React error boundary. If a Client Component throws during rendering, Next.js catches it and renders your error.tsx component instead of crashing the whole page, passing the caught error object and a reset function as props.

error.tsx must be a Client Component (it needs "use client") because error boundaries rely on client-side React lifecycle behavior. It only catches errors from nested Client Components rendered within its segment — errors thrown directly during server rendering of a Server Component behave slightly differently and are also caught by the nearest error.tsx.

// app/dashboard/error.tsx
"use client";

export default function Error({
  error,
  reset,
}: {
  error: Error;
  reset: () => void;
}) {
  return (
    <div>
      <p>Something went wrong: {error.message}</p>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

reset() attempts to re-render the segment, which is useful when the error was caused by a transient issue like a flaky network request.

error.tsx and not-found.tsx File Conventions

app/
  dashboard/
    error.tsx        // catches runtime errors in this segment
    not-found.tsx     // shown when notFound() is called here
    page.tsx
  • error.tsx must include "use client" and receives error and reset as props.
  • not-found.tsx requires no special props and renders whenever notFound() is called within its segment.
  • Calling the notFound() function (from next/navigation) immediately triggers the nearest not-found.tsx.
  • Both files are optional; without them, Next.js falls back to a generic default error/404 page.

Error Handling Cheat Sheet

The pieces involved in Next.js error and not-found handling.

File / Function Purpose
error.tsx Client error boundary for a route segment
reset() Prop passed to error.tsx; attempts to re-render
not-found.tsx UI shown for missing content in this segment
notFound() Function (from next/navigation) that triggers not-found.tsx
global-error.tsx Catches errors in the root layout itself

Triggering a Custom 404 with notFound()

For dynamic routes, you often need to show a 404 when the requested resource simply doesn't exist — for example, a blog post ID that isn't in the database. Calling notFound() immediately stops rendering and shows the nearest not-found.tsx.

import { notFound } from "next/navigation";

export default async function PostPage({
  params,
}: {
  params: { id: string };
}) {
  const post = await getPost(params.id);
  if (!post) {
    notFound();
  }

  return <h1>{post.title}</h1>;
}

global-error.tsx for the Root Layout

A regular error.tsx cannot catch errors thrown by the root layout itself, since the layout wraps the error boundary. For that specific case, Next.js supports a special app/global-error.tsx file, which must render its own <html> and <body> tags since it replaces the entire layout when triggered.

  • global-error.tsx lives directly in app/, alongside the root layout.
  • It only activates for errors the regular error.tsx boundaries can't catch.
  • It must render a full <html>/<body> document, unlike regular error.tsx files.

Common Mistakes

  • Forgetting the "use client" directive on error.tsx, which causes a build error.
  • Assuming reset() fixes the underlying problem automatically — it only re-attempts rendering.
  • Using notFound() for authentication failures instead of redirect() to a login page.
  • Not adding any error.tsx, leaving users with Next.js's generic, unstyled default error screen in production.

Key Takeaways

  • error.tsx automatically wraps a route segment in a client-side error boundary.
  • It receives error and a reset() function, letting users retry without a full reload.
  • not-found.tsx renders whenever notFound() is called within its segment.
  • global-error.tsx is a special case for catching errors thrown by the root layout itself.
  • Both files are optional, but adding them is important for a polished production experience.

Pro Tip

Add at least one error.tsx near the root of your app/ directory as a safety net for the whole application, then add more specific error.tsx files deeper in the tree for sections where you want a more tailored recovery experience.