🛡️ Next.js Error & Not Found: Your App’s Safety Net
The Story of the Helpful Guard
Imagine your Next.js app is a magical castle. Sometimes visitors try to open doors that don’t exist, or machines inside break unexpectedly. Without guards, visitors would be lost and confused!
Error files are like friendly guards who catch problems and help visitors instead of leaving them stranded. Let’s meet these helpful guards!
🎯 What You’ll Learn
- error.js - Catches errors in a specific part of your app
- global-error.js - Catches errors everywhere (the boss guard!)
- Error Recovery UI - The helpful message shown when things break
- Reset Error Boundary - The “try again” button
- not-found.js - The guide for lost visitors
- notFound Function - How to send visitors to the “lost” page
📁 error.js File
What Is It?
Think of error.js like a safety net under a tightrope walker. If something goes wrong in your page, this file catches the error and shows a friendly message instead of a scary crash.
How It Works
'use client'
export default function Error({
error,
reset
}) {
return (
<div>
<h2>Oops! Something broke</h2>
<p>{error.message}</p>
<button onClick={() => reset()}>
Try Again
</button>
</div>
)
}
Key Points
| Part | What It Does |
|---|---|
'use client' |
Must be a Client Component |
error |
The problem that happened |
reset |
Function to try again |
Where To Put It
app/
├── dashboard/
│ ├── page.js
│ └── error.js ← Catches errors here
├── shop/
│ ├── page.js
│ └── error.js ← Catches errors here
Each folder can have its own error guard!
🌍 global-error.js File
What Is It?
global-error.js is the boss guard - it catches errors that happen in the root layout itself. It’s your app’s last line of defense!
The Difference
graph TD A[Root Layout Error] --> B{Which catches it?} B --> C[global-error.js ✓] D[Page Error] --> E{Which catches it?} E --> F[error.js ✓]
The Code
'use client'
export default function GlobalError({
error,
reset
}) {
return (
<html>
<body>
<h2>Something went very wrong!</h2>
<button onClick={() => reset()}>
Try Again
</button>
</body>
</html>
)
}
Why html and body Tags?
When global-error activates, it replaces the entire root layout. So you need to provide the basic HTML structure yourself!
💡 Remember:
global-error.jsgoes in theapp/folder root, not in subfolders.
🎨 Error Recovery UI
What Is It?
The Error Recovery UI is what users see when an error happens. It should be:
- Friendly - Not scary tech words
- Helpful - Tell them what to do
- Pretty - Match your app’s style
Building a Great Error UI
'use client'
export default function Error({ error, reset }) {
return (
<div className="error-container">
{/* Friendly Icon */}
<span className="icon">😅</span>
{/* Clear Message */}
<h2>Whoops! A hiccup occurred</h2>
{/* Simple Explanation */}
<p>
Don't worry! This happens sometimes.
</p>
{/* Clear Action */}
<button onClick={() => reset()}>
Give it another try
</button>
{/* Alternative Option */}
<a href="/">Go back home</a>
</div>
)
}
What Makes Good Error UI?
| Do This ✅ | Not This ❌ |
|---|---|
| “Something went wrong” | “Error 500: Internal Server Exception” |
| “Try again” button | Nothing to click |
| Friendly emoji 😊 | Red scary warnings |
| Match your design | Plain unstyled text |
🔄 Reset Error Boundary
What Is It?
The reset function is like a magic retry button. When users click it, Next.js tries to show the content again without reloading the whole page.
How Reset Works
graph TD A[Error Happens] --> B[Error UI Shows] B --> C[User Clicks Reset] C --> D{Try Again} D -->|Works!| E[Content Shows] D -->|Fails| B
Using Reset Properly
'use client'
import { useEffect } from 'react'
export default function Error({ error, reset }) {
// Log error for debugging
useEffect(() => {
console.log('Error:', error)
}, [error])
return (
<div>
<h2>Oops!</h2>
<button
onClick={() => reset()}
>
Try Again
</button>
</div>
)
}
What Reset Does
- Clears the error state
- Re-renders the error boundary children
- Tries again to show the content
💡 Pro Tip: If the error keeps happening, the reset will keep showing the error UI. Consider adding a “Go Home” link as backup!
🔍 not-found.js File
What Is It?
When someone tries to visit a page that doesn’t exist (like /pizza-party when you don’t have that page), not-found.js shows them a friendly “page not found” message.
Simple Example
export default function NotFound() {
return (
<div>
<h2>Page Not Found</h2>
<p>
We looked everywhere but
couldn't find this page!
</p>
<a href="/">Go back home</a>
</div>
)
}
Where To Put It
app/
├── not-found.js ← Root not found
├── blog/
│ └── not-found.js ← Blog not found
├── shop/
│ └── not-found.js ← Shop not found
Each section can have its own custom “not found” page!
Make It Fun!
export default function NotFound() {
return (
<div className="not-found">
<span className="big-emoji">🔍</span>
<h2>Lost in Space!</h2>
<p>
This page must have floated away.
Let's get you back on track!
</p>
<a href="/" className="home-button">
🏠 Take Me Home
</a>
</div>
)
}
📢 notFound Function
What Is It?
The notFound() function lets you programmatically show the not-found page. It’s like a guard who can send visitors to the “lost and found” area when needed.
When To Use It
import { notFound } from 'next/navigation'
async function getProduct(id) {
const product = await fetchProduct(id)
// If product doesn't exist
if (!product) {
notFound() // Show not-found page!
}
return product
}
Real Example
import { notFound } from 'next/navigation'
export default async function BlogPost({
params
}) {
const post = await getPost(params.slug)
// No post? Show not found!
if (!post) {
notFound()
}
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
)
}
How It Works
graph TD A[User visits /blog/xyz] --> B[Fetch post 'xyz'] B --> C{Post exists?} C -->|Yes| D[Show post] C -->|No| E[notFound called] E --> F[not-found.js shown]
Key Rules
| Rule | Why |
|---|---|
| Call in Server Components | Works during rendering |
| Stops execution | Nothing after notFound() runs |
| Shows nearest not-found.js | Uses your custom page |
🎯 Quick Summary
| File/Function | Purpose | Key Thing to Remember |
|---|---|---|
error.js |
Catch errors in segments | Must be 'use client' |
global-error.js |
Catch root layout errors | Needs <html> and <body> |
| Error Recovery UI | What users see | Be friendly, not scary |
reset() |
Try again without reload | Pass it from props |
not-found.js |
Show 404 pages | Can be per-segment |
notFound() |
Trigger 404 programmatically | Import from next/navigation |
🌟 The Complete Picture
graph TD A[User Visits Page] --> B{Page Exists?} B -->|No| C[not-found.js] B -->|Yes| D{Load Content} D -->|Error!| E{Where's error?} E -->|In segment| F[error.js] E -->|In root layout| G[global-error.js] F --> H[Show reset button] G --> H H --> I[User clicks reset] I --> D D -->|Success!| J[Show Page]
🎉 You Did It!
Now you know how to:
✅ Create error.js to catch segment errors ✅ Use global-error.js for root layout errors ✅ Build friendly Error Recovery UI ✅ Use reset() to try again ✅ Create not-found.js for 404 pages ✅ Call notFound() when data doesn’t exist
Your Next.js app now has the friendliest guards in town! 🛡️