Lesson 7 of 81
A route segment can be slow, can throw, or can point at something that doesn't exist — and the App Router has a dedicated file for each of those three states, wired up automatically, no manual boundary-wrangling required.
11 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A bug throws during rendering inside `app/dashboard/layout.tsx` itself. Will `app/dashboard/error.tsx` catch it?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Four special files give a route segment fallback UI for the states a page can be in besides "done and correct":
loading.tsx — an instant loading state, shown while the segment's content is still resolving.error.tsx — a fallback shown when something inside the segment throws during rendering.not-found.tsx — a fallback shown when the segment calls notFound(), or when a URL doesn't match any route.global-error.tsx — the last-resort fallback for errors in the root layout itself.The first three aren't manually wired boundaries — dropping the file in a route folder is the wiring. loading.tsx automatically wraps the segment in a React <Suspense> boundary; error.tsx automatically wraps it in a React error boundary. You get the behavior for free just by naming the file correctly.
// app/dashboard/loading.tsx
export default function Loading() {
return <DashboardSkeleton />;
}
// app/dashboard/error.tsx
"use client"; // Error boundaries must be Client Components
export default function Error({
error,
retry,
}: {
error: Error & { digest?: string };
retry: () => void;
}) {
return (
<div>
<h2>Something went wrong loading the dashboard.</h2>
<button onClick={() => retry()}>Try again</button>
</div>
);
}
// app/dashboard/not-found.tsx
export default function NotFound() {
return <p>That dashboard view doesn't exist.</p>;
}
loading.tsx wraps not-found.tsx, page.tsx, and any nested layout.tsx in a <Suspense> boundary — so the skeleton shows immediately while the segment streams in, and the shared layout around it stays interactive the whole time. error.tsx wraps that same set of children in an error boundary, so any throw during rendering — a failed fetch, a bad notFound()-adjacent bug, whatever — swaps in the error UI instead of taking down the app. retry() re-fetches and re-renders the segment's children, exactly what a "Try again" button should do; there's also a lower-level reset() prop for the rarer case where you want to clear the error state without re-fetching.
error.tsx must be a Client Component. React error boundaries only work as classes/hooks that run on the client, so Next.js requires "use client" at the top — a Server Component error.tsx fails outright.error.tsx doesn't catch errors in its own segment's layout.tsx or template.tsx. It only wraps what's rendered inside those — the fix for a layout-level bug is an error.tsx one level up.global-error.tsx replaces the entire root layout when it activates, so it must define its own <html> and <body> tags, plus any global styles or fonts the fallback needs — it doesn't inherit anything from app/layout.tsx.global-error.tsx can't export metadata or generateMetadata, because error boundaries have to be Client Components and those exports are Server Component-only.not-found.tsx triggers two different ways: calling notFound() explicitly inside a segment, or landing on a URL nothing in the app matches. The nearest not-found.tsx up the tree from wherever notFound() was called handles the first case; the root app/not-found.tsx is the catch-all for the second."Where would you put error handling for a dashboard with three nested sub-routes, and what happens if the bug is in the layout itself?" tests whether a candidate actually understands the boundary's placement rules, not just that error.tsx exists — the layout exception is exactly the kind of detail that separates "read the docs once" from "debugged this in production."