Skip to content

Intermediate · Modules, errors, JSON and dates · topic 27 of 61 · 30 min

Error handling: try, catch, finally and throw

Explanation

When something goes wrong, JavaScript throws an error object that stops normal execution. try/catch lets you catch it and react, finally runs clean-up code either way, and throw lets you raise your own errors with clear messages. Good error handling validates input early, never hides errors silently, and gives users a helpful message.

What is an error?

An error (also called an exception) is an object that describes a problem. When code throws one, the current function stops immediately and the error travels up the call stack until some code catches it. If nothing catches it, the program crashes (in Node) or the console shows "Uncaught …" (in the browser).

output
const user = null;
console.log(user.name);
// TypeError: Cannot read properties of null (reading 'name')

Built-in error types

TypeTypical cause
TypeErrorUsing a value the wrong way: calling undefined, reading a property of null
ReferenceErrorUsing a variable that does not exist, or a let/const in its TDZ
RangeErrorA number out of range: new Array(-1), too much recursion, toFixed(200)
SyntaxErrorCode (or JSON.parse input) that is not valid
ErrorThe general type you usually throw yourself

Every error has a name ('TypeError'), a message (the human text) and usually a stack (the list of function calls that led to it, with file names and line numbers). Read the first line of the stack that points to YOUR code.

try, catch and finally

javascript
function parseAmount(text) {
  try {
    const n = JSON.parse(text);          // may throw SyntaxError
    console.log('parsed');
    return n;
  } catch (error) {
    console.log('Could not parse:', error.message);
    return 0;
  } finally {
    console.log('done');                 // runs in every case
  }
}
parseAmount('42');    // parsed, done
parseAmount('4 2');   // Could not parse: …, done

Order: the try block runs; if it throws, the rest of try is skipped and catch runs; finally runs at the end whether there was an error or not, even after a return. Use finally for clean-up: closing a file, hiding a loading spinner.

Throwing your own errors

javascript
function withdraw(balance, amount) {
  if (typeof amount !== 'number' || amount <= 0) {
    throw new RangeError(`Invalid amount: ${amount}`);
  }
  if (amount > balance) throw new Error('Insufficient balance');
  return balance - amount;
}
Always throw Error objects (new Error(...)), not strings: only Error objects carry a stack trace.

Custom error classes and cause

javascript
class NotFoundError extends Error {
  constructor(what) {
    super(`${what} not found`);
    this.name = 'NotFoundError';
  }
}
try {
  try {
    throw new NotFoundError('PNR 4521');
  } catch (inner) {
    throw new Error('Booking lookup failed', { cause: inner });  // wrap with cause
  }
} catch (e) {
  console.log(e.message, '←', e.cause.message);
  // Booking lookup failed ← PNR 4521 not found
}

With a custom class you can react to specific problems with instanceof: if (e instanceof NotFoundError) show a 404 page, otherwise re-throw.

Careful: Never swallow errors with an empty catch {}. The program carries on in a broken state and nobody knows why. At minimum log the error; better, handle the cases you understand and re-throw the rest: catch (e) { if (!(e instanceof NotFoundError)) throw e; … }.

Where to handle errors

  • Validate input at the boundaries (forms, API requests, file reads) and throw clear errors early.
  • Catch errors where you can do something useful: show a message, retry, use a default.
  • Let unexpected errors bubble up to one top-level handler that logs them.
Tip: Write error messages for the person who will read them at 2 a.m.: what failed, with which value, and ideally what to do. "Invalid amount: -50" beats "Error".

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Error handling: try, catch, finally and throw · 1/6

Error handling

In this lesson you will handle errors on purpose instead of letting the program crash.

Prefer a video by a teacher? Find free videos on “javascript error handling try catch finally throw custom errors” on YouTube ↗

In real life: Reading a bank statement file

A finance app imports a CSV bank statement. Some rows are broken. Instead of crashing on the first bad row, the importer catches the error for that row, records the line number and reason, and continues. At the end it shows "142 rows imported, 3 rows skipped" with the reasons.

javascript
const rows = ['2026-01-02,1500', 'bad row', '2026-01-05,-200'];
const ok = [], skipped = [];
rows.forEach((row, i) => {
  try {
    const [date, amount] = row.split(',');
    if (!amount) throw new Error('missing amount');
    ok.push({ date, amount: Number(amount) });
  } catch (e) {
    skipped.push(`line ${i + 1}: ${e.message}`);
  }
});
console.log(ok.length, skipped); // 2 ['line 2: missing amount']

Practice (0/3 done)

Task 1 · Code · Javascript

Write safeParse(text) that returns the parsed JSON value, or null if the text is not valid JSON. Use try/catch.

Task 2 · Code · Javascript

Write withdraw(balance, amount) that throws a RangeError with the message "Invalid amount" when amount is not a positive number, throws an Error with the message "Insufficient balance" when amount > balance, and otherwise returns the new balance.

Task 3 · Code · Javascript

Write runSteps(steps) where steps is an array of functions. Call each one in order inside try/catch. Return an object { done, failed } where done counts the steps that worked and failed is an array of the error messages. Always set a variable cleanedUp = true in finally.

Quick quiz

Question 1

1.When does finally run?

Question 2

2.null.length throws which error?

Question 3

3.Why throw new Error("…") instead of throw "…"?

Question 4

4.What is wrong with catch (e) {} ?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

When does finally run?

Answer: Always, after try (and catch)

finally runs in every case, even after return.

null.length throws which error?

Answer: TypeError

Reading a property of null is a TypeError.

Why throw new Error("…") instead of throw "…"?

Answer: Error objects carry a name and a stack trace

Strings can be thrown but have no stack, which makes debugging hard.

What is wrong with catch (e) {} ?

Answer: It hides the error so bugs go unnoticed

An empty catch swallows the problem silently.

When does a finally block run?Related

Answer: Always, whether or not an exception happened

finally is for guaranteed cleanup.

From Exceptions: try, catch, finally and custom exceptions

When does finally run?Related

Answer: Always, even after return

finally always runs (except if the JVM exits).

From Exceptions: try, catch and finally

Where in a traceback do you find the error type and message?Related

Answer: On the last line

The last line names the error and gives the message. The lines above show where it happened.

From Errors and exceptions

Which problem reaches your catch block even if you never check response.ok?Related

Answer: The phone has no internet connection

A network failure makes fetch reject. HTTP errors still give a response, so you must check ok and throw yourself.

From async/await and error handling

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Modules, errors, JSON and dates” before its exam: JSON: data in and out, Dates and times, Formatting numbers, money and text with Intl.
  2. Module 6 exam: Modules, errors, JSON and dates · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Map, Set, iterators, generators and regular expressions. 61 topics left in the course before the final exam.

← Previous: Modules: import and export