Q164: React Error Boundaries, Recovery and Fallback UI
What Interviewers Want To Evaluate
This question checks whether you can design resilient React applications. Interviewers want error boundary behavior, what boundaries catch, what they do not catch, reset strategy, route-level boundaries, logging, fallback design, Suspense interaction, user recovery, and testing.
Senior answers should describe error boundaries as product reliability boundaries.
Short Interview Answer
An error boundary catches rendering errors in its child component tree and shows fallback UI instead of unmounting the entire React app. It catches errors during render, lifecycle methods, and constructors in class components below it, but not event handler errors, async callback errors, server errors, or errors thrown inside the boundary itself. Good apps place boundaries around routes, panels, widgets, and risky integrations so users can recover without losing the whole workflow.
Detailed Interview Answer
Error boundaries are React components that catch render-time failures below them.
Historically they are class components.
class ErrorBoundary extends React.Component {
state = { error: null };
static getDerivedStateFromError(error) {
return { error };
}
componentDidCatch(error, info) {
reportError(error, info);
}
render() {
if (this.state.error) {
return this.props.fallback;
}
return this.props.children;
}
}
Many projects use a library wrapper, but the model is the same.
What Error Boundaries Catch
They catch errors thrown while React is rendering or committing child components.
render errors
constructor errors in class components
lifecycle errors in class components
errors thrown by child components during render
This prevents one broken subtree from crashing the entire app.
What Error Boundaries Do Not Catch
Error boundaries do not catch everything.
event handler errors
async errors in timers or promises
server-side rendering errors
errors thrown inside the boundary itself
errors outside React
Event handlers should use local try/catch or mutation error handling.
Async workflows should model loading and error state explicitly.
Boundary Placement
Placement determines blast radius.
root boundary protects the entire shell
route boundary protects a page
panel boundary protects a dashboard section
widget boundary protects third-party or risky UI
modal boundary protects an isolated workflow
One root boundary is not enough for a complex app because it turns small failures into whole-page failures.
Fallback UI
Fallback UI should be useful and calm.
explain that the section failed
keep unaffected navigation available
offer retry when retry can work
preserve user context when possible
show support or report details only when helpful
avoid exposing stack traces to users
log technical details separately
Fallbacks should match the scope of the boundary.
Reset Strategy
Users need a path back.
Common reset triggers:
retry button
route change
filter change
resource id change
modal close
manual reset from boundary API
If the same invalid props are still passed after reset, the error will happen again.
Reset is useful only when inputs or environment can change.
Logging and Observability
Error boundaries are useful collection points.
Log:
error message and stack
component stack
route
release version
user action context when safe
feature flag state
tenant or account id when allowed
browser and device signal
Respect privacy. Do not log sensitive form data.
Route-Level Boundaries in Next.js
Next.js App Router supports route segment error boundaries with error.tsx.
"use client";
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<section>
<h2>Page failed to load</h2>
<button onClick={reset}>Try again</button>
</section>
);
}
This lets a route segment fail without taking down the entire application shell.
Error Boundaries and Suspense
Suspense handles waiting. Error boundaries handle failure.
Suspense fallback: data or component is not ready yet
Error boundary fallback: rendering failed
They are often paired.
<ErrorBoundary fallback={<PanelError />}>
<Suspense fallback={<PanelSkeleton />}>
<Panel />
</Suspense>
</ErrorBoundary>
Event Handler Errors
Errors in event handlers happen after rendering.
function SaveButton() {
async function onClick() {
try {
await save();
} catch (error) {
setError(error);
}
}
return <button onClick={onClick}>Save</button>;
}
Use explicit mutation error state instead of expecting an error boundary to catch it.
Common Mistakes
A common mistake is relying only on a root boundary.
Another mistake is showing a vague blank fallback.
Another mistake is logging sensitive data.
Another mistake is using an error boundary to handle expected validation or network states.
Another mistake is retrying without changing the failed input or request state.
Senior Trade-Offs
Boundaries improve resilience, but too many boundaries can fragment UX.
Place them around meaningful failure domains: routes, expensive panels, third-party widgets, and workflows where partial recovery matters.
Code or Design Example
<DashboardShell>
<ErrorBoundary fallback={<RevenuePanelError />}>
<Suspense fallback={<RevenuePanelSkeleton />}>
<RevenuePanel />
</Suspense>
</ErrorBoundary>
</DashboardShell>
If revenue fails, navigation and other dashboard panels remain usable.
Debugging Workflow
When an error boundary appears:
check captured stack and component stack
identify failing release
reproduce with same route and flags
inspect props and data shape
verify whether fallback can reset
check whether error belongs in expected state
add regression test around the failed boundary
Interview Framing
Define what error boundaries catch. Explain placement, fallback design, reset, logging, Suspense pairing, and expected-error alternatives.
Revision Notes
Error boundaries are reliability boundaries. They should preserve as much user progress as possible.
Key Takeaways
A good boundary turns a crash into a recoverable local failure.
Follow-Up Questions
- What does an error boundary catch?
- What does it not catch?
- Why is one root boundary insufficient?
- Where should route-level boundaries live in Next.js?
- How should fallback UI behave?
- What makes reset useful?
- How do boundaries relate to Suspense?
- How should event handler errors be handled?
- What should be logged?
- How do you test error boundaries?
How I Would Answer This In A Real Interview
I would say error boundaries catch render-time failures below them and let the app show scoped fallback UI. I would place them around route and feature failure domains, pair them with Suspense where needed, log technical details privately, and design reset paths that preserve user progress.