Technology · Next.js

Next.js Error Handling

Implement custom error pages, error boundaries, and global error handling strategies.

TL;DR
  1. 01Create error.tsx files for segment-level error boundaries.
  2. 02Create not-found.tsx for 404 pages.
  3. 03Handle errors in server actions and API routes explicitly.

Error Boundaries with error.tsx

  • Create error.tsx for segment-level error handling.
    // app/blog/error.tsx
    "use client";
    
    import { useEffect } from "react";
    
    export default function Error({
      error,
      reset,
    }: {
      error: Error & { digest?: string };
      reset: () => void;
    }) {
      useEffect(() => {
        console.error(error);
      }, [error]);
      
      return (
        <div>
          <h2>Something went wrong!</h2>
          <button onClick={() => reset()}>Try again</button>
        </div>
      );
    }
  • Error boundaries catch errors from child segments.
  • Reset function allows users to retry.
  • Must be a client component with "use client" directive.

Custom 404 Pages

  • Create not-found.tsx for missing resources.
    // app/blog/[slug]/not-found.tsx
    export default function NotFound() {
      return (
        <div>
          <h1>Post not found</h1>
          <p>The post you're looking for doesn't exist.</p>
        </div>
      );
    }
  • Use notFound() function to trigger the not-found page.
    import { notFound } from "next/navigation";
    
    export default async function Post({ params }) {
      const post = await getPost(params.slug);
      if (!post) {
        notFound();
      }
      return <article>{post.content}</article>;
    }
  • Each segment can have its own not-found.tsx.
  • Add a root-level not-found.tsx for app-wide 404 handling.
    // app/not-found.tsx
    import Link from "next/link";
    
    export default function RootNotFound() {
      return (
        <div>
          <h1>Page not found</h1>
          <Link href="/">Go home</Link>
        </div>
      );
    }
  • Export metadata from not-found.tsx for SEO.
    export const metadata = {
      title: "404 — Page not found",
      description: "This page does not exist."
    };

Server Action Error Handling

  • Catch and handle errors in server actions.
    "use server";
    
    export async function createPost(formData: FormData) {
      try {
        const title = formData.get("title") as string;
        if (!title) {
          return { error: "Title is required" };
        }
        
        const post = await db.post.create({ data: { title } });
        return { success: true, post };
      } catch (error) {
        return { error: "Failed to create post" };
      }
    }
  • Return error objects from server actions.
  • Handle errors in client components.
    "use client";
    
    export default function Form() {
      const [error, setError] = useState<string | null>(null);
      
      async function handleSubmit(formData: FormData) {
        const result = await createPost(formData);
        if (result.error) {
          setError(result.error);
        }
      }
      
      return (
        <form action={handleSubmit}>
          {error && <p>{error}</p>}
        </form>
      );
    }

API Route Error Handling

  • Return error responses with appropriate status codes.
    // app/api/posts/[id]/route.ts
    export async function GET(
      request: Request,
      { params }: { params: { id: string } }
    ) {
      try {
        const post = await getPost(params.id);
        if (!post) {
          return Response.json(
            { error: "Post not found" },
            { status: 404 }
          );
        }
        return Response.json(post);
      } catch (error) {
        return Response.json(
          { error: "Internal server error" },
          { status: 500 }
        );
      }
    }
  • Always handle errors in API routes explicitly.
  • Return meaningful status codes and error messages.
  • Validate request body fields and return 400 for bad input.
    export async function POST(request: Request) {
      const body = await request.json();
      if (!body.title) {
        return Response.json({ error: "Title is required" }, { status: 400 });
      }
      return Response.json({ ok: true });
    }
  • Return 401 for missing or invalid authentication tokens.
    const token = request.headers.get("authorization");
    if (!token || !isValid(token)) {
      return Response.json({ error: "Unauthorized" }, { status: 401 });
    }

Global Error Handling

  • Create a root error.tsx for unhandled errors.
    // app/error.tsx (root level)
    "use client";
    
    export default function RootError({
      error,
      reset,
    }: {
      error: Error & { digest?: string };
      reset: () => void;
    }) {
      return (
        <html>
          <body>
            <h1>Application Error</h1>
            <p>Something went wrong across the application.</p>
            <button onClick={() => reset()}>Try again</button>
          </body>
        </html>
      );
    }
  • Use error monitoring services like Sentry.
    useEffect(() => {
      Sentry.captureException(error);
    }, [error]);
  • Log errors for debugging and monitoring.
  • Create a global-error.tsx to catch errors in the root layout.
    // app/global-error.tsx
    "use client";
    
    export default function GlobalError({ reset }) {
      return (
        <html>
          <body>
            <h1>Something went wrong</h1>
            <button onClick={reset}>Try again</button>
          </body>
        </html>
      );
    }
  • Use the error digest to correlate client errors with server logs.
    export default function Error({ error }: { error: Error & { digest?: string } }) {
      return <p>Error ID: {error.digest}</p>;
      // digest matches the server-side error log entry
    }

Tip: Use error boundaries at multiple levels to provide context-specific error messages and recovery options for different parts of your app.

Warning: Never expose sensitive error details to users — log detailed errors server-side and show friendly messages to clients.

Next.js Environment VariablesNext.js Data Fetching