# Handling Errors with try, catch and finally

try runs code that might fail, catch takes over when it does and gets an error object with a name and a message, and finally runs either way, so one bad value doesn't stop your whole program.

Apprentice · JavaScript · Software Development · Updated November 1, 2026

## After this lesson you can

- Catch an error with try and catch, and read its name and message
- Use finally for code that must run whether or not an error happened

## Key takeaways

- An error that nothing catches stops the program, and every line after it is skipped.
- Put the code that might fail in a try block. When it throws, JavaScript jumps to the catch block and the program carries on.
- The catch block gets an error object. Its name says what kind of problem it was, and its message says what went wrong.
- A finally block runs whether the try block worked or failed, so clean-up code goes there.
- A catch should do something useful, such as showing a message or using a fallback, never hide the error in silence.

You've seen error messages since your first program: a typo, and Node stops with a red line of text. In a real app, some errors come from outside your code: a saved file that got damaged, a person who typed "ten" where a number goes, a website that didn't answer. A shopping app that hits one of those shouldn't go blank. It should say *Something went wrong, please try again* and keep working. This lesson shows how your code can expect a problem, catch it and carry on.

This chapter's running example is a **recipe scaler**: a small program that takes a recipe card, such as *Saturday Pancakes* (it serves 4), and works out the amounts for 10 people, in cups or in milliliters.

## When nothing catches an error

The scaler keeps its recipe cards as JSON text, the format you met in *JSON: Data You Can Save and Send*. `JSON.parse` turns that text back into an object. This card got cut off at the end: its closing `}` is missing.

```javascript
const savedRecipe = '{ "name": "Saturday Pancakes", "servings": 4 ';
const recipe = JSON.parse(savedRecipe);

console.log(`Making ${recipe.name}`);
console.log("Time to cook!");
```

`JSON.parse` can't read it, so it **throws an error**: it stops and reports the problem. Nothing in this program catches the error, so Node prints it and stops the whole program. Neither `console.log` line runs. Above the error, Node shows the text it couldn't read; then comes the error itself:

```text
SyntaxError: Expected ',' or '}' after property value in JSON at position 45 (line 1 column 46)
    at JSON.parse (<anonymous>)
```

The lines below these give the file and the line number, `2`, where `JSON.parse` was called, as in *Your First JavaScript Program*. An error like this, one that happens while the program is running, is called a **runtime error**.

## try and catch: a safety net

Think of a trapeze act at the circus. The performer tries the trick, and if they slip, the net catches them and the show goes on. JavaScript's net has two parts:

- **`try`** (read "try") holds the code that might fail.
- **`catch`** (read "catch") holds the code to run if it does.

```javascript
const savedRecipe = '{ "name": "Saturday Pancakes", "servings": 4 ';

try {
  const recipe = JSON.parse(savedRecipe);
  console.log(`Making ${recipe.name}`);
} catch (error) {
  console.log("That saved recipe is damaged, so here's a fresh card.");
}

console.log("Time to cook!");
```

```text
That saved recipe is damaged, so here's a fresh card.
Time to cook!
```

When `JSON.parse` throws, JavaScript skips the rest of the `try` block (the *Making* line never runs) and jumps straight into `catch`. After the `catch` block, the program carries on as normal, so *Time to cook!* prints. When nothing goes wrong, the `catch` block is skipped. The whole thing, `try` and `catch` together, is called a **try...catch statement**.

**Try it.** Make a file named `damaged-card.js` with the code above and run it with `node damaged-card.js`. Then add the missing `}` before the last `'` on the first line and run it again. Which lines print now?

## The error object: name and message

The word in parentheses after `catch`, here `error`, is a variable you name. JavaScript puts an **error object** in it: an object that describes what went wrong. Two of its properties do most of the work:

- **`name`**: what kind of error it is, such as `TypeError`.
- **`message`**: what went wrong, in words.

```javascript
const recipe = { name: "Saturday Pancakes", servings: 4 };

try {
  console.log(recipe.ingredients.length);
} catch (error) {
  console.log(`name: ${error.name}`);
  console.log(`message: ${error.message}`);
}
```

```text
name: TypeError
message: Cannot read properties of undefined (reading 'length')
```

This card has no `ingredients`, so `recipe.ingredients` is `undefined`, and `undefined` has no `length`. These are the error names you'll meet most:

| Name | What it usually means | An example that causes it |
|---|---|---|
| `SyntaxError` | Text that isn't valid code or valid JSON | `JSON.parse("four")` |
| `TypeError` | A value used in a way its type can't do | `undefined.length`, or calling something that isn't a function |
| `ReferenceError` | A name that doesn't exist | `servingz * 2` when the variable is `servings` |
| `RangeError` | A number outside the range allowed | `(2.5).toFixed(200)`: `toFixed` allows 0 to 100 digits |

## The stack: where it happened

An error object has one more useful property, **`stack`**: the error's name and message, then a list of where the program was when it happened, newest first. It's called a **stack trace**, because it lists the stack of function calls that led to the error (the **call stack**). When this program runs `console.log(error.stack)` in its catch block:

```javascript
function countIngredients(recipe) {
  return recipe.ingredients.length;
}

try {
  countIngredients({ name: "Saturday Pancakes" });
} catch (error) {
  console.log(error.stack);
}
```

the first lines it prints are these (on your computer the folder part of the path is your own, shown here as `…`):

```text
TypeError: Cannot read properties of undefined (reading 'length')
    at countIngredients (…/stack.js:2:29)
    at Object.<anonymous> (…/stack.js:6:3)
```

Read it from the top: the error happened in `countIngredients`, on line 2, character 29, and `countIngredients` was called from line 6. `Object.<anonymous>` is Node's name for the top level of the file, the code that isn't inside any function. When an error surprises you, the top line of the stack trace that's in *your* file is where to look first.

## finally: it runs either way

After you cook, you put the recipe card back in the box, whether the pancakes turned out or not. That's **`finally`** (read "finally"): a third block that runs after `try` and `catch`, every time, whether there was an error or not.

```javascript
function readRecipeCard(text) {
  console.log("Taking the card out of the recipe box...");
  try {
    const recipe = JSON.parse(text);
    console.log(`Making ${recipe.name} for ${recipe.servings}.`);
  } catch (error) {
    console.log(`Can't read this card: ${error.message}`);
  } finally {
    console.log("Card back in the box.");
  }
}

readRecipeCard('{ "name": "Banana Bread", "servings": 8 }');
readRecipeCard('{ "name": "Banana Bread", "servings": ');
```

```text
Taking the card out of the recipe box...
Making Banana Bread for 8.
Card back in the box.
Taking the card out of the recipe box...
Can't read this card: Unexpected end of JSON input
Card back in the box.
```

The first card works, so `catch` is skipped; the second throws, so `catch` runs. Both times, `finally` runs. It even runs when the `try` block ends with a `return`. On a web page, `finally` is where a *Loading...* message gets hidden, so it disappears whether the data arrived or not.

## A catch should do something useful

A `catch` block that's empty, or that only says "oops", hides the problem: the program carries on with bad data, and nobody knows why. A useful catch does something a person can work with: it shows a clear message, or it uses a sensible fallback and says so.

```javascript
function loadServings(text) {
  try {
    return JSON.parse(text).servings;
  } catch (error) {
    console.log(`Couldn't read the saved servings (${error.message}). Using 4.`);
    return 4;
  }
}

console.log(loadServings('{ "servings": 6 }'));
console.log(loadServings("six"));
```

```text
6
Couldn't read the saved servings (Unexpected token 's', "six" is not valid JSON). Using 4.
4
```

Keep the `try` block small, too: wrap the line that can fail, not the whole program. Then a `catch` knows what went wrong.

**Try it.** In `damaged-card.js`, wrap the reading of the card in a function like `loadServings`, and call it with three texts: a good card, a card cut off halfway, and an empty string `""`. Print `error.name` and `error.message` in the catch block. Which error does the empty string give?

## Check yourself

2 questions to try on the lesson page.

## So what

Every app that reads files, forms or websites meets bad data sooner or later. With `try`, `catch` and `finally`, your program notices, says what went wrong, cleans up and keeps going, instead of stopping in front of the person using it.

## Key terms

- [try Block](https://www.ask-codey.com/glossary/try-block-javascript)
- [catch Block](https://www.ask-codey.com/glossary/catch-block-javascript)
- [finally Block](https://www.ask-codey.com/glossary/finally-block-javascript)
- [Error](https://www.ask-codey.com/glossary/error)
- [Runtime Error](https://www.ask-codey.com/glossary/runtime-error-javascript)
- Stack Trace

## Cheat sheets

- [Handling Errors with try, catch and finally](https://www.ask-codey.com/cheat-sheets/javascript-errors-try-catch-finally-cheat-sheet)

## Related

- [Throwing Your Own Errors](https://www.ask-codey.com/lessons/javascript-errors-throwing-your-own)

Source: https://www.ask-codey.com/lessons/javascript-errors-try-catch-finally
