← All lessons
Lesson 09 · Intermediate

Error Handling

Catch route-level errors with error.js, render not-found UIs, and use the `notFound()` helper.

Things go wrong: an API is down, a record doesn't exist, a database call throws. The App Router has two reserved files for handling this — error.js and not-found.js.

error.js

If anything inside a route segment throws, Next.js renders the closest error.js in place of that segment. The file must be a client component because it needs to handle a reset callback.

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

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

error.js catches errors from server and client components in the segment. It does not catch errors in the layout above it — for that, put an error.js one level higher.

notFound()

Use notFound() from next/navigation to bail out of rendering and show a 404. Pair it with a not-found.js file:

// app/blog/[slug]/page.js
import { notFound } from "next/navigation";

export default async function Post({ params }) {
  const { slug } = await params;
  const post = await getPost(slug);
  if (!post) notFound();
  return <article>{post.body}</article>;
}

// app/blog/[slug]/not-found.js
export default function NotFound() {
  return <p>Post not found.</p>;
}

global-error.js

If the root layout itself throws, normal error.js files can't save the day — there's no layout to render them inside. Add app/global-error.js for that. It must render its own <html> and <body>:

// app/global-error.js
"use client";

export default function GlobalError({ error, reset }) {
  return (
    <html>
      <body>
        <h1>Something broke at the top of the app.</h1>
        <button onClick={() => reset()}>Reload</button>
      </body>
    </html>
  );
}
Note: Don't put real diagnostics in user-facing error messages. Log to your server, show a friendly note. The error.digest property gives you a server-side id you can correlate with logs.

Try it

Update this page to return a proper 404 when no product is found, instead of an empty page.

Need a hint?

Import notFound from next/navigation and call it when the record is missing.

Quiz

Pick the best answer. You only get one shot per question.

1. Why must `error.js` be a client component?

2. Where does `error.js` catch errors from?

3. How do you trigger a 404 from inside a page component?