Handling Errors
Overview
Next.js provides several mechanisms for handling errors in your application, including error boundaries and error pages. Handling errors gracefully is essential for providing a good user experience. The focus of this learning activity will be on handling errors using JavaScript's try...catch statements and Next.js APIs for uncaught exceptions.
Prepare
Adding try...catch to Server Actions
When working with Server Actions, it's important to handle potential errors that may occur during data mutations. You can use try...catch blocks to catch and handle errors gracefully. For example:
export async function deleteProject(id: string) {
try {
await sql`DELETE FROM projects WHERE id = ${id}`;
revalidatePath('/projects');
} catch (error) {
console.error('Error deleting project:', error);
throw new Error('Failed to delete project. Please try again later.');
}
revalidatePath('/projects');
redirect('/projects');
}
In this example, if the database operation fails, the error is caught and logged, and a new error is thrown with a user-friendly message. This allows you to handle the error on the client side and provide feedback to the user.
Handling all errors with error.tsx
Next.js allows you to create a special error.tsx file in your app directory to handle uncaught exceptions. This file will be rendered whenever an error is thrown that is not caught by a try...catch block. You can customize this page to display a user-friendly error message and provide options for the user to navigate back to safety.
// /projects/error.tsx
'use client';
import Link from 'next/link';
import { useEffect } from 'react';
export default function Error({
error,
reset
}: {
error: Error & { digest: string };
reset: () => void
}) {
useEffect(() => {
// optionally log the error
console.error('An uncaught error occurred:', error);
}, [error]);
return (
<div className="mx-auto mt-16 max-w-xl rounded-lg border border-slate-200 bg-white p-6 text-center shadow-sm">
<h1 className="text-2xl font-bold text-slate-900">Something went wrong!</h1>
<p className="mt-3 text-slate-600">An unexpected error occurred. Please try again later.</p>
<div className="mt-6 flex flex-col items-center justify-center gap-3 sm:flex-row">
<button
onClick={reset}
className="rounded-md bg-blue-600 px-4 py-2 font-semibold text-white transition hover:bg-blue-700"
>
Try Again
</button>
<Link
href="/projects"
className="rounded-md border border-slate-300 px-4 py-2 font-semibold text-slate-700 transition hover:bg-slate-50"
>
Go Back to Projects
</Link>
</div>
</div>
);
}
Note the following:
- The error.tsx needs to be a Client Component and must use the
'use client'directive. - The
error:object is an instance of JavaScript's nativeErrorobject. - The
reset:function allows you to reset the error boundary and attempt to re-render the component that caused the error.
notFound function
Next.js also provides a notFound function that you can call to render a 404 page when a resource is not found. This is useful for handling cases where a user tries to fetch a resource that does not exist.
import { notFound } from 'next/navigation';
export default async function Page({ params }: { params: { id: string } }) {
const project = await getProjectById(params.id);
if (!project) {
notFound();
}
return <div>...</div>;
}
In this example, if the project with the specified ID is not found, the notFound function is called, which will render the 404 page.
To use the notFound function, make sure you have a not-found.tsx file in your directory. The not-found.tsx can look like this:
// /projects/[id]/edit/not-found.tsx
import Link from 'next/link';
export default function NotFound() {
return (
<div className="mx-auto mt-16 max-w-xl rounded-lg border
border-slate-200 bg-white p-6 text-center shadow-sm">
<h1 className="text-2xl font-bold text-slate-900">Project Not Found</h1>
<p className="mt-3 text-slate-600">The project you are looking for does not exist.</p>
<div className="mt-6 flex flex-col items-center justify-center gap-3 sm:flex-row">
<Link
href="/projects"
className="rounded-md border border-slate-300 px-4 py-2 font-semibold text-slate-700 transition hover:bg-slate-50"
>
Back to Projects
</Link>
</div>
</div>
);
}
In this example, if a user tries to access a project that does not exist, they will see a friendly message and a link to navigate back to the projects page.
Note that the notFound function will take precedence over error.tsx, which is useful when you want to display a specific 404 page for missing resources.