Day 13 — Error Handling: Breaking Gracefully
🧭 Day 13 — Error Handling: Breaking Gracefully
Zero to Hero — Hands-on Next.js Tutorial
In a perfect world, code never crashes. In the real world, APIs fail, databases timeout, and bugs happen. Next.js uses Error Boundaries to ensure that a crash in one part of your UI doesn’t break the whole app.
🟦 1. error.tsx
To handle runtime errors in a specific route segment, create an error.tsx file.
Next.js naturally wraps your page.tsx in a React Error Boundary.
Rules for error.tsx:
- Must be a Client Component (
'use client'). - Receives
errorandresetas props.
// src/app/dashboard/error.tsx
'use client'; // Error components must be Client Components
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error);
}, [error]);
return (
<div className="p-4 bg-red-50 border border-red-200 rounded">
<h2 className="text-red-800 font-bold">Something went wrong!</h2>
<button
onClick={() => reset()} // Attempt to recover by re-rendering the segment
className="bg-red-600 text-white px-4 py-2 mt-4 rounded hover:bg-red-700"
>
Try again
</button>
</div>
);
}
Now, if /dashboard/page.tsx throws an error, the user sees this UI instead of a white screen crash.
Critically, the Navigation (Sidebar/Header) stays visible and functional!
🟩 2. not-found.tsx
If you visit a route that doesn’t exist, Next.js serves a default 404.
You can customize this by creating not-found.tsx.
It also works programmatically!
// src/app/not-found.tsx
import Link from 'next/link';
export default function NotFound() {
return (
<div>
<h2>Not Found</h2>
<p>Could not find requested resource</p>
<Link href="/">Return Home</Link>
</div>
);
}
Triggering it manually:
import { notFound } from 'next/navigation';
async function fetchUser(id: string) {
const user = await db.user.findUnique({ where: { id } });
if (!user) {
notFound(); // Renders the nearest not-found.tsx
}
}
🟧 3. global-error.tsx
Your standard error.tsx cannot catch errors in the Root Layout (app/layout.tsx).
To handle crashes at the very top level, use global-error.tsx.
This file replaces your Root Layout, so it must define its own <html> and <body> tags.
🧪 Challenge: Day 13
- Create a page
/broken. - Inside the component, throw an error:
throw new Error("Oops!");. - Visit the page. See the default Next.js error overlay (in dev) or 500 page (prod).
- Create
app/broken/error.tsx. - Visit the page again. See your custom error UI?
- Click the “Reset” button (it won’t fix it because we hardcoded the throw, but it handles the interaction!).
See you tomorrow for Route Handlers (API Routes)! 🛠️