Next.js 15 Tutorial - 28 - Handling Errors in Layouts
I am a MERN stack developer. Here to learn and share my knowledge to help other to grow.
We've learned how error.tsx can gracefully handle runtime errors in pages and nested route segments.
But here's a catch most developers miss:
❗️ Errors thrown from a
layout.tsxfile in the same segment are not caught by that segment’serror.tsx.
If that sounds confusing, don’t worry — this post walks you through a practical example so you’ll never be surprised again.
📦 Folder Structure
Let’s assume the following structure:
/app
└── products
├── layout.tsx
├── error.tsx
└── [productId]
├── layout.tsx
└── page.tsx
Now let’s simulate an error in the [productId]/layout.tsx file — and see how the error boundary behaves (or doesn’t).
🧪 Simulating an Error in layout.tsx
Inside your [productId]/layout.tsx, paste the following:
// app/products/[productId]/layout.tsx
function getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
export default function ProductLayout({ children }: { children: React.ReactNode }) {
if (getRandomInt(2) === 1) {
throw new Error('Error loading product');
}
return (
<div>
<h2>Product Layout</h2>
{children}
</div>
);
}
⛔️ Step 1: Add error.tsx in the Same Segment
// app/products/[productId]/error.tsx
'use client';
export default function Error({ error }: { error: Error }) {
return <div>Error in Product: {error.message}</div>;
}
❌ Result
When you refresh the page, you might expect this error boundary to kick in. But it doesn't.
Instead, you'll see:
A runtime error screen
Your custom error message in the console
No recovery UI from your
error.tsxfile
🧠 Why This Happens
This behavior has to do with the component hierarchy in Next.js App Router:
layout.tsxcomponents render aboveerror.tsxboundaries.So, errors thrown in
layout.tsxcannot be caught byerror.tsxin the same segment.
✅ Step 2: Move error.tsx to the Parent Segment
To fix this, move your error boundary to the parent segment — in this case, products.
// app/products/error.tsx
'use client';
export default function Error({ error }: { error: Error }) {
return <div>Top-level Products Error: {error.message}</div>;
}
Now refresh the page again.
✅ Result
The error is now caught.
Your custom error UI is displayed.
The rest of the app (like global
layout.tsx, header, footer) continues to render smoothly.
🔁 Summary Table
| Segment | Error Location | Where to Put error.tsx | Catches Error? |
/products/[productId] | page.tsx or [reviewId]/page.tsx | /products/[productId]/error.tsx ✅ | ✅ |
/products/[productId] | layout.tsx | /products/error.tsx | ✅ |
/products/[productId] | layout.tsx | /products/[productId]/error.tsx | ❌ |
✨ Takeaways
layout.tsxrenders before the segment’serror.tsx, so its errors aren't caught there.To catch layout-level errors, place
error.tsxin a parent folder.Always think in terms of the component tree, not just folder structure.
🧠 Bonus Tip
Want to simulate a layout failure in development?
Just use:
if (getRandomInt(2) === 1) {
throw new Error('Something went wrong in layout');
}
Refresh until it breaks — then verify which error.tsx kicks in.
🚀 Final Thoughts
Error boundaries in Next.js App Router are powerful but nuanced. When layouts are involved, be mindful of their place in the render tree:
✅ Pages & children → error boundaries in the same folder
❌ Layouts → error boundaries must be higher up
Understanding this distinction helps you build more resilient, user-friendly apps.
🧩 Presentation Title
Handling Layout Errors in Next.js – Smart Boundaries with error.tsx
🔧 Powered by Revive Coding
Slide 1: 🧠 From Nested Routes to Layouts
We've mastered nested route error handling
Now let’s go one level higher ➡️ Layouts!
Layouts behave differently in the component tree
Let’s break it down 👇
Slide 2: 🔍 Layout & Error Boundary – The Caveat
error.tsxhandles errors in child segmentsBut there's a catch with layout.tsx
If an error is thrown inside a layout in the same segment,
👉 The localerror.tsxwon't catch it ❌
🧠 Why? Layouts sit above the boundary in the tree!
Slide 3: 🛠️ Demo Setup in VS Code
What we’ll do:
Copy
error.tsxtoproductId/routeIn
layout.tsx, simulate an error with:
if (getRandomInt(2) === 1) {
throw new Error("🚫 Error loading product");
}
🧪 Expectation: Local boundary handles it
🧨 Reality: App crashes!
Slide 4: 🔍 Error in Layout? App Breaks!
Reload the page a few times
🛑 Boom! Unhandled runtime error
We see
"Error loading product"in the consoleBut ❌ no boundary UI from
error.tsx
This proves: Error boundary was skipped due to layout’s position in the tree
Slide 5: ✅ Solution – Move the Boundary Up
- Move
error.tsxto the parent segment —/products/
app/
products/
error.tsx ⬅️ move here
[productId]/
layout.tsx
Now when we reload:
✅ Layout error gets caught
✅ Boundary UI replaces product content only
✅ Header, Footer, etc., remain unaffected
Slide 6: 🔁 Component Hierarchy Recap
Layout.tsx (productId) ← error not caught here
└─ error.tsx (productId) ❌ Won't work
└─ page.tsx ✅ Works for children
✔ Move error.tsx to products/
Layout.tsx (productId)
└─ error.tsx (products) ✅ Will catch it
📌 Always place error boundaries above the layout that might fail
Slide 7: 💡 Key Takeaways
❗ Errors from layout.tsx won’t be caught by same-segment
error.tsx✅ Always place error.tsx in parent folder for layout safety
🔧 This allows recovery without crashing full app
💯 Layout-safe boundaries = Stable UX
Slide 8: 📌 Summary
Nested segment errors → handled by local error.tsx
Layout errors → need parent level error boundary
Knowing the component tree = mastering recovery
🧠 Think hierarchy. Catch early. Recover fast.
Slide 9: 🙌 What’s Next?
Next: Advanced fallback UIs & retry patterns in layout recovery
More control. Better resilience. Real-world edge cases
🔔 Like & Subscribe to Revive Coding to stay updated
It’s free and keeps us building better content ❤️
🔧 Bonus: Suggested File Structure After Fix
app/
products/
error.tsx ✅ handles layout + page errors
[productId]/
layout.tsx ⚠️ throw simulated error
page.tsx ✅ standard rendering
🎤 Slide 1: 🧠 From Nested Routes to Layouts
Hindi Script:
"नमस्कार दोस्तों!
अब तक हमने सीखा कि nested routes में errors को कैसे handle करना है।
लेकिन अब बारी है एक और ज़रूरी हिस्से की —
और वो है layouts के अंदर error handling।
Layout components थोड़े अलग behave करते हैं,
और इस difference को समझना बहुत ज़रूरी है।
चलिए, शुरू करते हैं!"
🔍 Slide 2: Layout & Error Boundary – The Caveat
Hindi Script:
"आपको याद होगा कि error.tsx सभी nested segments के लिए error को catch करता है।
लेकिन layouts के साथ एक छोटा twist है।
अगर layout में ही error आता है, और error.tsx उसी segment में है —
तो वो boundary काम नहीं करेगी।
क्यों? क्योंकि layout component tree में error boundary से ऊपर बैठा होता है।"
🛠️ Slide 3: Demo Setup in VS Code
Hindi Script:
"अब इसको practical तरीके से देखते हैं।
हम error.tsx को [productId] फोल्डर में कॉपी करते हैं।
फिर [productId]/layout.tsx में वही random error logic डालते हैं
जो हमने पहले [reviewId]/page.tsx में यूज़ किया था।
if (getRandomInt(2) === 1) {
throw new Error("🚫 Error loading product");
}
और अब देखते हैं क्या होता है।"
🔍 Slide 4: Error in Layout? App Breaks!
Hindi Script:
"Browser में जब हम page reload करते हैं और error trigger होता है —
तो UI टूट जाता है, और हमें console में दिखता है "Error loading product"।
लेकिन कोई भी error boundary UI render नहीं होता।
इसका मतलब है कि error.tsx को ये error मिला ही नहीं।
और यही है हमारा key learning point।"
✅ Slide 5: Solution – Move the Boundary Up
Hindi Script:
"इस problem को solve करने के लिए हमें करना होगा एक छोटा सा adjustment।
हमें error.tsx को [productId] से उठाकर parent segment, यानी /products/ में रखना होगा।
अब जब हम page reload करते हैं:
✅ Layout का error catch होता है
✅ और सिर्फ product की content replace होती है
✅ बाकी UI — जैसे header, footer — वैसा का वैसा रहता है"
🔁 Slide 6: Component Hierarchy Recap
Hindi Script:
"चलिए hierarchy को एक बार फिर से समझते हैं।
Layout.tsx (productId) ← error not caught here
└─ error.tsx (productId) ❌ Won’t work
└─ page.tsx ✅ Works for children
जब हम error.tsx को /products/ में रखते हैं —
तब ही layout level error सही से catch होता है।"
💡 Slide 7: Key Takeaways
Hindi Script:
"तो दोस्तों, कुछ बातें हमें पक्के तौर पर याद रखनी चाहिए:
❗ Layout.tsx के errors को उसी segment का error.tsx handle नहीं कर सकता
✅ Boundary को parent folder में रखें
🔧 इससे आपका app stable रहता है और टूटता नहीं
💯 Layout-safe boundaries = Better UX"
📌 Slide 8: Summary
Hindi Script:
"तो एक बार फिर से recap करते हैं:
Nested errors को हम local boundaries से संभाल सकते हैं।
लेकिन Layout errors के लिए boundary को ऊपर रखना ज़रूरी है।
इससे हमारा app graceful तरीके से recover कर सकता है।
किसी भी component को stable बनाना है — तो hierarchy को समझना सबसे बड़ा हथियार है।"
🙌 Slide 9: What’s Next?
Hindi Script:
"आगे हम बात करेंगे advanced fallback UIs और retry patterns की —
जिससे हमारी layout recovery और भी स्मार्ट हो जाएगी।
अगर ये वीडियो आपके काम आया हो — तो Like करें, Subscribe करें, और Revive Coding को support करें।
ये हमें motivation देता है और आपके लिए ज़्यादा quality content लाने में मदद करता है।
मिलते हैं अगले वीडियो में — तब तक के लिए, Happy Coding!"
