Most frontend code assumes happy paths. Production reality is messier — APIs fail, networks drop, user devices crash, browsers behave unpredictably. The interview probes whether you understand error handling as a systematic concern, not an afterthought.
The categories of error
- Network errors: request fails, times out, returns non-200
- Application errors: JavaScript exception in user code
- Validation errors: user input does not match expectations
- Authorization errors: 401/403 responses
- Browser errors: ResizeObserver loop, quota exceeded, etc.
React error boundaries
Class components with componentDidCatch catch errors in their child tree:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
componentDidCatch(error, info) { logError(error, info); }
render() { return this.state.hasError ? <Fallback /> : this.props.children; }
}
Wrap top-level routes and risky subtrees. Without boundaries, errors crash the entire app.
Where to put boundaries
- Around the entire app (catches crashes, shows fallback)
- Around each route
- Around third-party widgets
- Around isolated features that can fail independently
Don’t boundary every component — performance and UX cost.
Network error handling
Use a data layer that handles errors:
- TanStack Query has built-in retry with exponential backoff
- React Query gives you isError, error, refetch in hooks
- Manual fetch needs explicit try/catch + retry logic
Best practice: render a meaningful error state with a retry button, not a blank screen.
Distinguish error types
Different errors need different UX:
- Network failure: “Connection lost; tap to retry”
- 5xx server error: “Something went wrong on our end”
- 4xx client error: show specific message (“This item was not found”)
- 401: redirect to login
- 403: “You do not have access”
Retry logic
For transient errors (network, 5xx):
- Retry with exponential backoff (1s, 2s, 4s, 8s)
- Cap at 3–5 attempts
- Don’t retry idempotent vs non-idempotent the same way (do not retry POSTs blindly)
For permanent errors (4xx), do not retry — show the user.
Optimistic updates and rollback
If a write fails:
- Local state had been updated optimistically
- Network call fails
- Roll back local state to pre-write
- Show error toast with retry option
Without rollback, UI lies — shows success when reality is failure.
Global error logging
Capture errors in production:
- window.onerror for unhandled exceptions
- window.onunhandledrejection for unhandled promise rejections
- React error boundaries’ componentDidCatch
Send to Sentry, Bugsnag, Datadog RUM, or your own backend. Include user context, breadcrumbs, and source maps.
Source maps in production
Without source maps, error reports show minified gibberish. Upload source maps to your error tracker; never serve them publicly (they expose source code).
Breadcrumbs
Track user actions leading up to the error:
- Page navigations
- API calls (just URLs, not bodies)
- UI interactions (button clicks)
- State changes
When the error fires, breadcrumbs help reproduce.
Fallback UI
Bad fallback: “Something went wrong” with no actionable info.
Good fallback:
- Specific to the failure (“Could not load posts”)
- Actionable (Retry button)
- Preserves context (don’t crash the entire page if one widget failed)
- Never blank — always show something
Common antipatterns
- Generic “Error” toast for every failure
- No retry mechanism
- White screen of death (no error boundary at root)
- Silent error swallowing (catch + ignore)
- Logging errors to console only (lost in production)
Frequently Asked Questions
Should I show the actual error message to users?
For dev errors: usually no. For network or validation errors: yes if useful. Generic message + retry is the safe default.
What about service errors during streaming responses?
Streaming (SSE, LLM token streams) need different handling. Show partial output, then error message, then retry option.
How do I prevent error infinite loops?
Error boundaries should not re-render their fallback in a way that triggers errors. Test fallbacks deliberately.