Skip to main content

Command Palette

Search for a command to run...

Error Handling in JavaScript: Try, Catch, Finally

Updated
4 min read

Error handling in JavaScript isn’t just about avoiding crashes — it’s about controlling failure in a predictable way so your app behaves well even when something goes wrong.

In my experience, most bugs in real projects are not because logic is wrong, but because errors are not handled properly.

Let’s break this down cleanly 👇


🔹 1. What errors are in JavaScript

Errors are problems that stop your code from running correctly.


✅ Common types of errors

🔸 Syntax Error (code is invalid)

if (true {
  console.log("Hello");
}

👉 Missing ) → code won’t even run


🔸 Reference Error (variable not defined)

console.log(x);

🔸 Type Error (wrong operation)

null.toUpperCase();

🔸 Runtime Error (error during execution)

JSON.parse("invalid json");

🔹 2. Using try...catch

👉 Lets you handle errors without crashing the app

try {
  const data = JSON.parse("invalid json");
} catch (error) {
  console.log("Something went wrong:", error.message);
}

🔑 Flow

  • try → run code
  • if error → jump to catch
  • app continues running

🔹 3. The finally block

👉 Runs no matter what (error or not)

try {
  console.log("Trying...");
} catch (e) {
  console.log("Error!");
} finally {
  console.log("Always runs");
}

💡 Use cases

  • closing DB connection
  • stopping loaders
  • cleanup tasks

🔹 4. Throwing custom errors

👉 You can create your own errors using throw

function withdraw(balance, amount) {
  if (amount > balance) {
    throw new Error("Insufficient balance");
  }
  return balance - amount;
}

Catch it

try {
  withdraw(100, 200);
} catch (e) {
  console.log(e.message);
}

🔹 Custom error types (advanced)

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

👉 I usually use custom errors when I want better control over different error types.


🔹 5. Why error handling matters

This is the real reason 👇


✅ 1. Prevent app crashes

Without handling:

JSON.parse("bad"); // app breaks ❌

With handling:

try {
  JSON.parse("bad");
} catch {
  console.log("Handled");
}

✅ 2. Better user experience

Instead of showing:

👉 App crashed

We can show:

👉 "Something went wrong, try again"


✅ 3. Debugging becomes easier

catch (e) {
  console.log(e.message);
}

✅ 4. Control program flow

if (!user) {
  throw new Error("User not found");
}

✅ 5. Security (important)

Don’t expose internal errors:

catch (e) {
  res.status(500).send("Server error");
}

👉 This is important when working with backend APIs.


⚠️ Common mistakes


❌ Catching but ignoring

catch (e) {}

👉 This hides bugs 😬


❌ Using try/catch everywhere

👉 Use it only where errors are expected:

  • API calls
  • JSON parsing
  • async operations

❌ Not handling async errors properly

try {
  await fetchData();
} catch (e) {}

👉 This works only with async/await, not with .then()


❌ Not returning or rethrowing errors

try {
  riskyTask();
} catch (e) {
  console.log(e);
}

👉 Sometimes you should rethrow:

catch (e) {
  throw e;
}

💡 Final takeaway

  • Errors = things that break your code
  • try...catch = safely handle them
  • finally = always runs
  • throw = create your own errors
  • Good error handling = stable + professional apps