Async & Modern JSIntermediate6 min19 / 23

Error Handling

Catch and recover from failures with try/catch/finally, throw your own errors, and handle rejected promises.

Things go wrong — bad input, a failed network request, a missing file. Error handling lets your program respond gracefully instead of crashing. The core tool is try...catch.

try / catch / finally
try {
  const data = JSON.parse(userInput); // may throw
  console.log(data.name);
} catch (err) {
  console.log('Could not parse:', err.message);
} finally {
  console.log('This always runs, error or not.');
}

Code in try runs normally; if anything throws, control jumps to catch with the error object. finally runs either way — perfect for cleanup.

#Throwing your own errors

throw when something is invalid
function withdraw(balance, amount) {
  if (amount > balance) {
    throw new Error('Insufficient funds');
  }
  return balance - amount;
}

try {
  withdraw(50, 100);
} catch (e) {
  console.log(e.message); // Insufficient funds
}
Common mistake

try/catch doesn't catch async callbacks

A try/catch only catches errors thrown synchronously in its block. For promises, either use .catch(), or await inside a try/catch block (async/await makes rejected promises throwable). A plain setTimeout callback that throws won't be caught by an outer try/catch.

with async/await
async function load() {
  try {
    const res = await fetch('/api/user');
    if (!res.ok) throw new Error('HTTP ' + res.status);
    return await res.json();
  } catch (e) {
    console.log('Load failed:', e.message);
    return null;
  }
}
Quick check

When does the `finally` block run?

Key takeaways

  • `try` runs code; if it throws, `catch (err)` handles the error; `finally` always runs.
  • Use `throw new Error('message')` to signal an invalid situation.
  • The caught error object has a `.message` (and `.name`, `.stack`).
  • Plain try/catch only catches synchronous throws — use `.catch()` or `await` in try/catch for promises.
Practice challenges
Test yourself · earn XP
0/3
Predict the output#1

What does this print?

predict-output
try {
  throw new Error('boom');
} catch (e) {
  console.log('caught:', e.message);
} finally {
  console.log('cleanup');
}
Fix the bug#2

The rejected fetch isn't being caught. What's the fix?

fix-bug
try {
  fetch('/api').then(r => r.json());
} catch (e) {
  console.log('failed');
}
Fill in the blank#3

Complete the statement that signals an invalid amount.

if (amount < 0)  new Error('amount must be positive');
Your turn
Practice exercise

Write safeParse(text) that returns the parsed JSON, or null if parsing fails (instead of throwing).

Try it live — edit the code and hit Run to see the output:

solution.js · editable