ReviseAlgo Logo

JS Fundamentals

Error Handling

Master JavaScript error handling. Understand try, catch, finally, throw statements, standard Error classes, and async error patterns.

Last Updated: July 15, 2026 10 min read

1. Introduction

Even correct code can experience unexpected failures at runtime due to network issues, bad user inputs, or API outages. JavaScript provides error handling keywords to intercept and recover from these errors.

2. Why It Matters

Unhandled errors crash execution. Implementing structured error handling prevents application crashes, logs helpful diagnostics, and provides a smooth experience for users.

3. Real-World Analogy

Think of Traversing a Tightrope:

  • try: Walking along the rope (attempting to run risky operations like parsing data).
  • throw: Experiencing a strong gust of wind that knocks you off balance (raising an exception).
  • catch: A safety net placed below the rope. It catches your fall, keeps you safe, and lets you recover instead of falling to the ground (program crashing).
  • finally: Dusting off your clothes and packing your gear. You do this whether you walked across successfully or fell into the net.

4. How It Works

Error handling is implemented using four core constructs:

  • try: Encloses code that might throw an error.
  • catch: Runs only if an error is thrown inside the try block. It receives the thrown error object.
  • finally: Runs always, after the try and catch blocks finish, regardless of the outcome.
  • throw: Creates and raises a custom error.

5. Standard Errors

JavaScript has several built-in error types:
ReferenceError: Raised when referencing an undeclared variable.
TypeError: Raised when a value is not of the expected type (e.g. calling a non-function).
SyntaxError: Raised when parsing syntactically invalid code.
RangeError: Raised when a numeric value is outside its allowed range.

6. Practical Example

Here is an example demonstrating input validation and custom error propagation:

7. Common Mistakes

  • Trying to catch async errors synchronously: A synchronous try-catch block cannot intercept errors thrown inside asynchronous callbacks or unresolved promises.
  • Throwing plain strings: Always throw instances of the Error class (or its subclasses) so that stack trace metrics are generated. Avoid throwing strings like throw "error occurred".

8. Quick Quiz

Q1: Which block is guaranteed to execute regardless of whether an exception is thrown or caught?

A) catch

B) finally

Answer: B — The finally block always runs after execution exits the try or catch blocks.

9. Scenario-Based Challenge

The Resilient API Client:

You are designing a data loader that fetches users. If the request fails due to a network error, you want to retry the request 3 times before finally logging an error to the user interface. Outline the logical retry steps.

10. Debugging Exercise

Fix the error handling block to intercept the asynchronous exception:

function fetchUserData() {
  return new Promise((resolve, reject) => {
    reject(new Error('Server offline'));
  });
}

try { fetchUserData(); } catch (e) { console.log('Caught client exception: ' + e.message); // Doesn't run! }

View Solution

Diagnosis: The promise rejection occurs asynchronously, so the synchronous try-catch block finishes executing before the error is thrown.

Fix: Use promise .catch() handlers or await the asynchronous call within an async function:

// Option 1: Promise Catch
fetchUserData().catch(e => console.error('Caught:', e.message));

// Option 2: Async Await async function init() { try { await fetchUserData(); } catch (e) { console.error('Caught:', e.message); } } init();

11. Interview Questions

🟢 Q1: How do you handle unhandled promise rejections globally in Node.js and the browser?

Answer:
• In the browser, listen for the unhandledrejection window event:
window.addEventListener('unhandledrejection', event => { ... });.
• In Node.js, register a listener on the process object for the unhandledRejection event:
process.on('unhandledRejection', (reason, promise) => { ... });.

12. Production Considerations

  • Cleanup Resources: Always release locks, close file streams, and clear active timers inside the finally block, ensuring they are freed even if preceding steps throw exceptions.