MindForge
MindForge
DashboardHelp & Support
Dashboard
MindForge

Interview Preparation Bootcamp

Course progress

0%
0 of 177 modules complete
Start Here0/1
  • How to Use This Course
Data Structures & Algorithms0/27
  • Arrays and Hashing
  • Two Pointers
  • Sliding Window
  • Sliding Window: Harder Problems
  • Binary Search
  • Stacks
  • Practice Test: Arrays, Pointers, Windows, Search and Stacks
  • Trees: Traversals and Core Patterns
  • Binary Search Trees and Rebuilding a Tree
  • Tries (Prefix Trees)
  • Heaps and Priority Queues
  • Graphs: BFS and DFS
  • Topological Sort and Cycle Detection
  • Union-Find (Disjoint Set Union)
  • Practice Test: Trees, Heaps and Graphs
  • Dynamic Programming Basics
  • Dynamic Programming: Two Dimensions
  • Dynamic Programming: Hard String Matching
  • Backtracking
  • Backtracking: Constraint Satisfaction
  • Greedy Algorithms
  • Interval Problems
  • Bit Manipulation
  • Math and Geometry
  • String Manipulation
  • Pattern Recall and Mock Coding Rounds
  • Practice Test: DP, Backtracking, Greedy and More

System Design

Foundations0/16
  • The System Design Interview Framework
  • Back-of-the-Envelope Estimation
  • Networking and Protocols for Design
  • API Design and Idempotency
  • Load Balancing, Proxies, and Scaling Out
  • Caching and CDNs
  • Choosing a Database: Storage, Indexes and Transactions
  • Replication, Partitioning, and Sharding
  • CAP, PACELC, and Levels of Consistency
  • Messaging, Queues, and Event-Driven Architecture
  • Distributed Transactions and Data Integrity
  • Coordination, Consensus, and Distributed Locks
  • Reliability, Resilience, and Rate Limiting
  • Observability, Security, and Cost
  • System Design Cheat Sheet
  • Practice Test: System Design Foundations
Case Studies0/23
  • Design a URL Shortener
  • Design a Rate Limiter
  • Design a Notification Service
  • Design a Job Queue System
  • Design a Chat App (WhatsApp)
  • Design an Analytics Pipeline
  • Design a Multi-tenant SaaS Architecture
  • Design a Social Media Feed (Twitter/X)
  • Design a Search Autocomplete System
  • Design a File Storage Service (Dropbox)
  • Design Google Docs
  • Design a Code Review System
  • Design Netflix
  • Design YouTube
  • Design Spotify
  • Design Uber/Lyft
  • Design Airbnb
  • Design Ticketmaster (Eventbrite)
  • Design an E-commerce Cart, Checkout, and Catalog
  • Design a Payment System
  • Design a Logging and Monitoring System
  • Mock Design Rounds
  • Practice Test: System Design Case Studies
Low-Level Design0/19
  • The LLD Interview Framework and UML
  • OOP Foundations for Design
  • SOLID Principles
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns I — Strategy, Observer, Command, State, Template Method
  • Behavioral Patterns II and Anti-Patterns
  • Concurrency in Low-Level Design
  • Design a Parking Lot
  • Design an Elevator System
  • Design a Movie Ticket Booking System
  • Design an Expense-Sharing App (Splitwise)
  • Design a Vending Machine and an ATM
  • Design a Rate Limiter and a Logging Framework
  • Design a Notification Service and an In-Memory Cache
  • Design Games — Tic-Tac-Toe, Snake and Ladder, Chess
  • Database Design for LLD
  • LLD Cheat Sheet and Recall Drill
  • Practice Test: Low-Level Design

Backend

Python0/5
  • How Python Runs Your Code
  • Functions Deep Dive: Closures, Generators, Context Managers, Scope
  • Classes Deep Dive: Method Types, MRO, Metaclasses
  • Standard Library and Serialization
  • Practice Test: Python
Django0/6
  • Django Request Lifecycle
  • Lab: Django Middleware — Request ID & Response Time
  • Django ORM and Querysets
  • Django's Cache Framework
  • Practice Test: Django
  • Django in Production: Debugging Labs
FastAPI0/5
  • FastAPI, ASGI, and Async
  • FastAPI Dependency Injection
  • FastAPI Background Tasks
  • Lab: FastAPI Async — Concurrent Aggregation
  • Practice Test: FastAPI
Databases (PostgreSQL)0/6
  • Indexing
  • Query Optimization
  • Transactions and Isolation
  • Migrations and Schema Changes
  • Hierarchical Data and Safe Concurrent Updates
  • Practice Test: Databases
Caching, Queues & Distributed Systems0/8
  • Redis Caching
  • Redis Advanced Patterns
  • Celery and Background Workers
  • Kafka and Message Queues
  • Async Pipelines
  • Distributed Systems Basics
  • Distributed Locks
  • Practice Test: Caching, Queues and Distributed Systems
APIs, Security & Deployment0/9
  • REST API Design
  • API Versioning and Error Handling
  • API Security and Authentication
  • WebSockets and Real-Time Systems
  • Docker and Containers
  • File Storage with S3
  • Testing Strategies
  • Mock Backend Round
  • Practice Test: APIs, Security and Deployment
Frontend0/38
  • HTML Document Structure and Semantics
  • CSS Box Model, Flexbox and Grid
  • CSS Architecture and Theming
  • CSS and Rendering Performance
  • Variables, Scope, Hoisting, and Truthiness
  • Functions, this, and Binding
  • Objects and Prototypal Inheritance
  • JavaScript Utility Patterns: Cloning, Caching, and Memory
  • Promises From Scratch
  • The Event Loop and Browser Rendering Pipeline
  • The DOM: Nodes, Events, and Traversal
  • Practice Test: HTML, CSS and JavaScript
  • React Rendering Fundamentals
  • React Hooks Internals
  • React Performance
  • Lab: React — Stateful Counter Component
  • State Management
  • State Machines in React
  • React Custom Hooks and Composition Patterns
  • TypeScript for React
  • React Testing
  • Practice Test: React
  • HTTP and Caching
  • Network Performance and Web Vitals
  • Code Splitting and Bundles
  • Virtualization
  • GraphQL and Data Fetching
  • Web Security
  • WebSockets and Real-time
  • SSR and Next.js
  • Micro-frontends
  • Build Tools and Bundling
  • Accessibility
  • Error Handling
  • Internationalization
  • Animation
  • Rapid Recall and Mock Frontend Rounds
  • Practice Test: Performance, Architecture and Production
Behavioral & Interview Day0/14
  • Resume and Project Walkthroughs
  • The STAR Method and Refining Your Stories
  • Conflict and Difficult Coworkers
  • Failures, Incidents, and Obstacles
  • Leadership, Mentorship, and Ownership
  • Teamwork, Communication, and Feedback
  • Growth and Handling Ambiguity
  • Career Goals, Why This Company, and Negotiation
  • Situational Questions
  • Company Research
  • Mock Behavioral Rounds
  • Interview Day
  • After the Interview
  • Practice Test: Behavioral and Interview Day
Error Handling
Course contents

Interview Preparation Bootcamp

Course progress

0%
0 of 177 modules complete
Start Here0/1
  • How to Use This Course
Data Structures & Algorithms0/27
  • Arrays and Hashing
  • Two Pointers
  • Sliding Window
  • Sliding Window: Harder Problems
  • Binary Search
  • Stacks
  • Practice Test: Arrays, Pointers, Windows, Search and Stacks
  • Trees: Traversals and Core Patterns
  • Binary Search Trees and Rebuilding a Tree
  • Tries (Prefix Trees)
  • Heaps and Priority Queues
  • Graphs: BFS and DFS
  • Topological Sort and Cycle Detection
  • Union-Find (Disjoint Set Union)
  • Practice Test: Trees, Heaps and Graphs
  • Dynamic Programming Basics
  • Dynamic Programming: Two Dimensions
  • Dynamic Programming: Hard String Matching
  • Backtracking
  • Backtracking: Constraint Satisfaction
  • Greedy Algorithms
  • Interval Problems
  • Bit Manipulation
  • Math and Geometry
  • String Manipulation
  • Pattern Recall and Mock Coding Rounds
  • Practice Test: DP, Backtracking, Greedy and More

System Design

Foundations0/16
  • The System Design Interview Framework
  • Back-of-the-Envelope Estimation
  • Networking and Protocols for Design
  • API Design and Idempotency
  • Load Balancing, Proxies, and Scaling Out
  • Caching and CDNs
  • Choosing a Database: Storage, Indexes and Transactions
  • Replication, Partitioning, and Sharding
  • CAP, PACELC, and Levels of Consistency
  • Messaging, Queues, and Event-Driven Architecture
  • Distributed Transactions and Data Integrity
  • Coordination, Consensus, and Distributed Locks
  • Reliability, Resilience, and Rate Limiting
  • Observability, Security, and Cost
  • System Design Cheat Sheet
  • Practice Test: System Design Foundations
Case Studies0/23
  • Design a URL Shortener
  • Design a Rate Limiter
  • Design a Notification Service
  • Design a Job Queue System
  • Design a Chat App (WhatsApp)
  • Design an Analytics Pipeline
  • Design a Multi-tenant SaaS Architecture
  • Design a Social Media Feed (Twitter/X)
  • Design a Search Autocomplete System
  • Design a File Storage Service (Dropbox)
  • Design Google Docs
  • Design a Code Review System
  • Design Netflix
  • Design YouTube
  • Design Spotify
  • Design Uber/Lyft
  • Design Airbnb
  • Design Ticketmaster (Eventbrite)
  • Design an E-commerce Cart, Checkout, and Catalog
  • Design a Payment System
  • Design a Logging and Monitoring System
  • Mock Design Rounds
  • Practice Test: System Design Case Studies
Low-Level Design0/19
  • The LLD Interview Framework and UML
  • OOP Foundations for Design
  • SOLID Principles
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns I — Strategy, Observer, Command, State, Template Method
  • Behavioral Patterns II and Anti-Patterns
  • Concurrency in Low-Level Design
  • Design a Parking Lot
  • Design an Elevator System
  • Design a Movie Ticket Booking System
  • Design an Expense-Sharing App (Splitwise)
  • Design a Vending Machine and an ATM
  • Design a Rate Limiter and a Logging Framework
  • Design a Notification Service and an In-Memory Cache
  • Design Games — Tic-Tac-Toe, Snake and Ladder, Chess
  • Database Design for LLD
  • LLD Cheat Sheet and Recall Drill
  • Practice Test: Low-Level Design

Backend

Python0/5
  • How Python Runs Your Code
  • Functions Deep Dive: Closures, Generators, Context Managers, Scope
  • Classes Deep Dive: Method Types, MRO, Metaclasses
  • Standard Library and Serialization
  • Practice Test: Python
Django0/6
  • Django Request Lifecycle
  • Lab: Django Middleware — Request ID & Response Time
  • Django ORM and Querysets
  • Django's Cache Framework
  • Practice Test: Django
  • Django in Production: Debugging Labs
FastAPI0/5
  • FastAPI, ASGI, and Async
  • FastAPI Dependency Injection
  • FastAPI Background Tasks
  • Lab: FastAPI Async — Concurrent Aggregation
  • Practice Test: FastAPI
Databases (PostgreSQL)0/6
  • Indexing
  • Query Optimization
  • Transactions and Isolation
  • Migrations and Schema Changes
  • Hierarchical Data and Safe Concurrent Updates
  • Practice Test: Databases
Caching, Queues & Distributed Systems0/8
  • Redis Caching
  • Redis Advanced Patterns
  • Celery and Background Workers
  • Kafka and Message Queues
  • Async Pipelines
  • Distributed Systems Basics
  • Distributed Locks
  • Practice Test: Caching, Queues and Distributed Systems
APIs, Security & Deployment0/9
  • REST API Design
  • API Versioning and Error Handling
  • API Security and Authentication
  • WebSockets and Real-Time Systems
  • Docker and Containers
  • File Storage with S3
  • Testing Strategies
  • Mock Backend Round
  • Practice Test: APIs, Security and Deployment
Frontend0/38
  • HTML Document Structure and Semantics
  • CSS Box Model, Flexbox and Grid
  • CSS Architecture and Theming
  • CSS and Rendering Performance
  • Variables, Scope, Hoisting, and Truthiness
  • Functions, this, and Binding
  • Objects and Prototypal Inheritance
  • JavaScript Utility Patterns: Cloning, Caching, and Memory
  • Promises From Scratch
  • The Event Loop and Browser Rendering Pipeline
  • The DOM: Nodes, Events, and Traversal
  • Practice Test: HTML, CSS and JavaScript
  • React Rendering Fundamentals
  • React Hooks Internals
  • React Performance
  • Lab: React — Stateful Counter Component
  • State Management
  • State Machines in React
  • React Custom Hooks and Composition Patterns
  • TypeScript for React
  • React Testing
  • Practice Test: React
  • HTTP and Caching
  • Network Performance and Web Vitals
  • Code Splitting and Bundles
  • Virtualization
  • GraphQL and Data Fetching
  • Web Security
  • WebSockets and Real-time
  • SSR and Next.js
  • Micro-frontends
  • Build Tools and Bundling
  • Accessibility
  • Error Handling
  • Internationalization
  • Animation
  • Rapid Recall and Mock Frontend Rounds
  • Practice Test: Performance, Architecture and Production
Behavioral & Interview Day0/14
  • Resume and Project Walkthroughs
  • The STAR Method and Refining Your Stories
  • Conflict and Difficult Coworkers
  • Failures, Incidents, and Obstacles
  • Leadership, Mentorship, and Ownership
  • Teamwork, Communication, and Feedback
  • Growth and Handling Ambiguity
  • Career Goals, Why This Company, and Negotiation
  • Situational Questions
  • Company Research
  • Mock Behavioral Rounds
  • Interview Day
  • After the Interview
  • Practice Test: Behavioral and Interview Day
Browsing without an account — progress is saved in this browser only.Sign in to save it

Error Handling

Reading30 min

Every production frontend fails in the field eventually: a network drops, an API sends back broken JSON, a third-party script throws. Interviewers ask about error handling to see whether you design for that reality, or only for the happy path.

Error boundaries, and their real limits

An error boundary catches JavaScript errors thrown while rendering, in lifecycle methods, and in constructors of the tree below it, and shows a fallback instead of crashing the whole app. As of React 19 it's still only possible as a class component, there's no hook version, because the underlying mechanism, getDerivedStateFromError/componentDidCatch, needs instance behavior only a class gives you.

tsx
class ErrorBoundary extends Component<{ fallback: (error: Error, reset: () => void) => ReactNode; onError?: (error: Error, info: ErrorInfo) => void; children: ReactNode }, { error: Error | null }> {
  state = { error: null as Error | null };
  static getDerivedStateFromError(error: Error) { return { error }; } // runs during render
  componentDidCatch(error: Error, info: ErrorInfo) { this.props.onError?.(error, info); } // runs after render — the right place to log
  reset = () => this.setState({ error: null });
  render() {
    if (this.state.error) return this.props.fallback(this.state.error, this.reset);
    return this.props.children;
  }
}
tsx
<ErrorBoundary
  fallback={(error, reset) => <div role="alert"><p>Something went wrong: {error.message}</p><button onClick={reset}>Try again</button></div>}
  onError={(error, info) => reportToSentry(error, info.componentStack)}
>
  <Dashboard />
</ErrorBoundary>

What error boundaries do not catch is the most common trap here, worth knowing cold. Errors inside event handlers, an onClick throwing, are ordinary JavaScript errors, catch those with try/catch right in the handler. Errors inside async code, a setTimeout, a promise, a fetch callback, since by the time the callback runs, React is no longer "inside" a render it can intercept. Errors during server-side rendering. And an error thrown inside the boundary's own render, a boundary can't catch its own failure, a second boundary nested above it is the only way to cover that.

There's no built-in fix for the async and event-handler gaps, catch those by hand, and if you want the nearest boundary to actually handle one, re-throw it during a state update so the next render is what actually throws:

tsx
function DangerousButton() {
  const [, setError] = useState();
  return (
    <button onClick={() => {
      try { riskyOperation(); }
      catch (err) { setError(() => { throw err; }); } // re-throw during render so the nearest boundary catches it
    }}>Run</button>
  );
}

In production code, most teams reach for the react-error-boundary package instead of hand-writing the class above, same mechanism, better ergonomics: a useErrorBoundary hook for the manual-throw pattern, and a resetKeys prop that auto-resets when relevant props change.

tsx
import { ErrorBoundary } from "react-error-boundary";
function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback} onError={(error, info) => reportToSentry(error, info)} onReset={() => window.location.reload()}>
      <Dashboard />
    </ErrorBoundary>
  );
}

Remember: an error boundary only catches errors thrown while rendering. It never catches an error from an event handler, a promise, or a timer.

Sign in to try this knowledge check.

What catches everything a boundary can't

Error boundaries only cover the React render tree. Two browser-level events catch what escapes it.

ts
// Uncaught synchronous errors anywhere on the page, including entirely outside React
window.addEventListener("error", (event) => {
  reportToSentry(event.error ?? new Error(event.message), { filename: event.filename, lineno: event.lineno });
});

// Unhandled promise rejections — exactly the async gap error boundaries can't cover
window.addEventListener("unhandledrejection", (event) => {
  reportToSentry(event.reason instanceof Error ? event.reason : new Error(String(event.reason)));
  event.preventDefault(); // suppress the default "Uncaught (in promise)" console noise
});

Most teams don't hand-write this either. Sentry, Bugsnag, and similar tools install both listeners automatically, and add resolved stack traces, a trail of recent user actions leading up to the error, and release tagging on top. Knowing what they actually hook into, error, unhandledrejection, plus componentDidCatch for React, is what interviewers are really probing for, not which vendor happens to be in use.

Remember: window.addEventListener("error", ...) and "unhandledrejection" are what catch exactly the two gaps error boundaries leave open.

Sign in to try this knowledge check.

Retrying transient failures without making things worse

Network calls fail transiently: a blip, a timeout, a momentarily overloaded server. Retrying with exponential backoff and jitter is the standard pattern, backing off exponentially so you don't hammer a server that's already struggling, and adding jitter, a small random amount, so many clients retrying at once don't all collide on the same schedule.

ts
async function fetchWithRetry(url: string, options?: RequestInit, { maxRetries = 3, baseDelayMs = 300, maxDelayMs = 5000 } = {}): Promise<Response> {
  let lastError: unknown;
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const res = await fetch(url, options);
      // Only retry on 5xx or 429 — a 4xx client error like 400/404 won't succeed on retry
      if (res.ok || (res.status < 500 && res.status !== 429)) return res;
      lastError = new Error(`HTTP ${res.status}`);
    } catch (err) { lastError = err; } // network failure, DNS error, etc.

    if (attempt < maxRetries) {
      const exponential = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
      const jitter = Math.random() * exponential * 0.3;
      await new Promise((resolve) => setTimeout(resolve, exponential + jitter));
    }
  }
  throw lastError;
}

Trace one failing call: attempt 0 gets a 503, lastError is set, and the loop waits about 300ms plus jitter before attempt 1. If attempt 1 also fails, the wait roughly doubles, capped at maxDelayMs. Once attempt exceeds maxRetries, the loop exits and the last error is thrown, so the caller sees a real error, not a silent undefined.

Four details interviewers listen for specifically. Which failures are worth retrying: a 404 or 400 fails identically every time, don't retry client errors; 5xx and 429 (respecting a Retry-After header if present) are the ones worth retrying. A retry ceiling: unbounded retries turn one transient blip into an indefinite hang from the user's view, always cap attempts and show a real final failure. Idempotency: retrying a POST that creates something can duplicate it if the first attempt actually succeeded but the response was lost in transit; GET/PUT/DELETE are safe to retry by definition, POST is risky without an idempotency key. Libraries: TanStack Query and SWR implement this exact pattern already, reach for one of them in real projects rather than hand-rolling retry logic, unless an interview specifically asks you to build it.

Remember: never retry a 4xx. It will fail the exact same way every time, and retrying it only wastes time and load.

Sign in to try this knowledge check.

Failing in a way the user can actually recover from

The goal isn't "never fail." It's failing in a way the user can understand and act on.

tsx
function DataPanel({ userId }: { userId: string }) {
  const { data, error, isLoading, refetch } = useUserData(userId);
  if (isLoading) return <Skeleton />;
  if (error) {
    if (error.status === 401) return <SignInPrompt />;
    if (error.status === 0) return <div role="alert"><p>You appear to be offline. Check your connection.</p><button onClick={refetch}>Retry</button></div>;
    return <div role="alert"><p>Couldn't load this data right now.</p><button onClick={refetch}>Retry</button></div>;
  }
  return <UserSummary data={data} />;
}

Three principles worth stating out loud. Give a specific message, never just "Something went wrong." Tell "you're offline" apart from "you're not signed in" apart from "the server failed," since each one has a different correct next step. Always offer a next action: retry, sign in again, contact support. An error with no action is a dead end. Let partial failures degrade gracefully. If a dashboard has five independent widgets and one API call fails, the other four should still work, wrap each widget in its own error boundary instead of one boundary around the whole page that takes everything down together.

tsx
function Dashboard() {
  return (
    <div className="grid">
      <ErrorBoundary fallback={() => <WidgetError name="Revenue" />}><RevenueWidget /></ErrorBoundary>
      <ErrorBoundary fallback={() => <WidgetError name="Traffic" />}><TrafficWidget /></ErrorBoundary>
    </div>
  );
}

Remember: wrap each independent widget in its own error boundary. One boundary around the whole page means one failing widget takes everything else down with it.

Sign in to try this knowledge check.

React's boundaries, the browser's global listeners, and a retry policy each cover a different failure surface, and a production app needs all three, plus UI that tells the user something specific and actionable happened, not just that something did.

PreviousAccessibilityNextInternationalization

Course progress

0%
0 of 177 modules complete

On this page

  • Error boundaries, and their real limits
  • What catches everything a boundary can't
  • Retrying transient failures without making things worse
  • Failing in a way the user can actually recover from