# Frontend Error Handling: Boundaries, Logging, and Recovery

Source: https://www.techinterview.org/post/3233475172/frontend-error-handling-boundaries-logging/
Updated: 2026-06-30 · techinterview.org

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.
