Skip to main content

Command Palette

Search for a command to run...

Error Handling in JavaScript: Try, Catch, Finally

Published
6 min read
Error Handling in JavaScript: Try, Catch, Finally
S
I write code , that run in the browser and someone else's machine. And sometimes I also write articles

When writing JavaScript programs, errors are inevitable. No matter how carefully you code, something unexpected can happen:

  • A variable might be undefined

  • An API might fail

  • A user might input invalid data

  • A file might not load

The real question is not whether errors happen.
The real question is how your program responds when they do.

Good error handling makes the difference between:

  • A crashing application

  • A graceful and controlled failure

Let us build this step by step.


What Are Errors in JavaScript

An error is a problem that prevents JavaScript from executing code normally.

There are different types of errors, but the most common for developers are runtime errors.

A runtime error happens while the program is running.


Simple Runtime Error Example

console.log(user.name);

If user is not defined, JavaScript throws:

ReferenceError: user is not defined

What happens next?

  • JavaScript stops execution.

  • Any code after this line does not run.

  • The application may break.

This is why error handling is important.


Another Example: Invalid Operation

const num = 10;
num();

This causes:

TypeError: num is not a function

Again, execution stops immediately.

Without proper handling, one small mistake can stop your entire program.


The Problem Without Error Handling

Consider this example:

console.log("Start");

let result = JSON.parse("invalid json");

console.log("End");

JSON.parse("invalid json") throws an error because the string is not valid JSON.

Output:

Start
SyntaxError: Unexpected token i in JSON

"End" never prints.

The program crashes at the error point.

This is called unhandled error.


Using Try and Catch

To prevent crashes, JavaScript provides the try...catch mechanism.

Basic structure:

try {
  // risky code
} catch (error) {
  // handle error
}

Let us rewrite the previous example safely.

console.log("Start");

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

console.log("End");

Output:

Start
Something went wrong: Unexpected token i in JSON
End

Now:

  • The error is caught.

  • The program continues running.

  • Execution does not stop.

This is called graceful failure.


How Try and Catch Work Internally

Step by step:

  1. JavaScript enters the try block.

  2. If no error occurs, the catch block is skipped.

  3. If an error occurs, execution jumps immediately to catch.

  4. The error object is passed into the catch parameter.

  5. The program continues after the catch block.

Important detail:

Only runtime errors inside the try block are caught.
Syntax errors outside execution cannot be caught.


The Error Object

Inside catch, you receive an error object.

try {
  undefinedFunction();
} catch (error) {
  console.log(error.name);
  console.log(error.message);
}

Common properties:

  • error.name → Type of error

  • error.message → Description

  • error.stack → Stack trace

This information is extremely useful for debugging.


The Finally Block

The finally block runs no matter what happens.

Structure:

try {
  // risky code
} catch (error) {
  // handle error
} finally {
  // always runs
}

Example:

try {
  console.log("Trying something...");
  throw new Error("Something failed");
} catch (error) {
  console.log("Caught error:", error.message);
} finally {
  console.log("Cleanup complete");
}

Output:

Trying something...
Caught error: Something failed
Cleanup complete

Even if an error occurs, finally executes.


Why Finally Is Useful

It is commonly used for:

  • Closing database connections

  • Stopping loaders

  • Releasing resources

  • Logging completion

Example:

function processFile() {
  try {
    console.log("Opening file...");
    throw new Error("File corrupted");
  } catch (error) {
    console.log("Error processing file");
  } finally {
    console.log("Closing file...");
  }
}

processFile();

Even if processing fails, the file is "closed."


Throwing Custom Errors

Sometimes you want to create your own error.

Use the throw keyword.

function divide(a, b) {
  if (b === 0) {
    throw new Error("Division by zero is not allowed");
  }

  return a / b;
}

try {
  console.log(divide(10, 0));
} catch (error) {
  console.log("Custom Error:", error.message);
}

This allows you to:

  • Validate inputs

  • Enforce business rules

  • Stop invalid operations early


Creating Specific Error Types

JavaScript has built-in error types:

  • Error

  • TypeError

  • ReferenceError

  • SyntaxError

  • RangeError

Example:

throw new TypeError("Invalid data type provided");

Choosing the correct error type improves clarity.


Why Error Handling Matters

Error handling is not just about preventing crashes. It is about building reliable systems.

Without error handling:

  • Applications crash unexpectedly

  • Users see blank screens

  • Debugging becomes harder

  • Production systems become unstable

With proper error handling:

  • Applications fail gracefully

  • Users see meaningful messages

  • Logs capture useful debugging details

  • Developers can trace issues quickly


Debugging Benefits

Consider this unsafe code:

const data = fetchData();
console.log(data.user.name);

If data.user is undefined, the program crashes.

With error handling:

try {
  const data = fetchData();
  console.log(data.user.name);
} catch (error) {
  console.error("Data structure issue:", error);
}

Now you:

  • Capture the problem

  • Log useful debugging information

  • Prevent full application failure

Good error messages make debugging 10 times easier.


Common Mistakes to Avoid

  • Catching errors and ignoring them silently

  • Using try/catch for normal control flow

  • Not logging error details

  • Catching errors too broadly

Example of bad practice:

try {
  riskyCode();
} catch (error) {
  // nothing
}

This hides problems and makes debugging difficult.


Conclusion

Errors are a natural part of JavaScript development. Runtime errors can stop program execution if not handled properly.

The try...catch structure allows you to:

  • Catch runtime errors

  • Prevent application crashes

  • Handle failures gracefully

The finally block ensures cleanup logic always runs.

The throw keyword allows you to create custom errors and enforce rules.

Proper error handling improves reliability, debugging, and overall software quality. It transforms fragile applications into stable and maintainable systems.