Skip to main content
Errors fall into two categories: expected errors that can occur during normal operation (like form validation failures), and unexpected exceptions that indicate bugs. This page covers how to handle both.

Handling expected errors

Expected errors should be modeled as return values, not thrown exceptions.

Server Functions

Use the useActionState hook to handle expected errors from Server Functions. Instead of throwing, return the error as a value:
In your Client Component, use useActionState to read the returned state and display the error:

Server Components

In a Server Component, use the fetch response to conditionally render an error message:

Not found

Call notFound() to render a 404 UI. Create a not-found.tsx file in the route segment to customize the UI:

Handling uncaught exceptions

Unexpected errors should be thrown. Next.js catches them with error boundaries and displays fallback UI.

The error.js convention

Create an error.tsx file inside a route segment to define an error boundary for that segment:
Errors bubble up to the nearest parent error boundary. Place error.tsx files at different levels in the route hierarchy to control the scope of error recovery. Component hierarchy with error boundary:
The error.tsx component must be a Client Component because it uses React lifecycle methods to catch and display errors during rendering.

Custom error boundaries with unstable_catchError

For component-level error recovery, use unstable_catchError to create error boundaries that wrap any part of your component tree:
Use the returned component as a wrapper:

Global errors

Handle errors in the root layout using global-error.tsx. This replaces the root layout when active, so it must include <html> and <body> tags:

Errors in event handlers

Error boundaries don’t catch errors inside event handlers — they only catch errors during rendering. For event handler errors, use try/catch with useState:

Errors in transitions

Unhandled errors inside startTransition from useTransition bubble up to the nearest error boundary:

Summary

Expected errors

Return errors as values from Server Functions. Use useActionState in Client Components to display them. Use notFound() for 404s.

Unexpected errors

Throw errors and let error boundaries catch them. Use error.tsx for route-level boundaries, global-error.tsx for the root layout.