Skip to main content

Command Palette

Search for a command to run...

Error Handling in JavaScript

Try, Catch and Finally

Updated
4 min read
Error Handling in JavaScript
S
Software Developer | Full Stack Developer |

What are Errors in JavaScript?

Errors in JavaScript are issues that occur during the execution of your code. These are typically categorized as:

  • Syntax Errors – Mistakes in code structure (caught before execution)

  • Runtime Errors – Occur while the program is running

  • Logical Errors – Code runs, but produces incorrect results

Example of a Runtime Error

let user = null;
console.log(user.name); // ❌ TypeError: Cannot read properties of null

This error occurs because you're trying to access a property (name) of a null value.

Error objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions. See below for standard built-in error types.

Using try...catch Blocks

To prevent your application from crashing due to runtime errors, JavaScript provides the try...catch mechanism. The try...catch construct has two main blocks: try, and then catch:

Basic Syntax:

try {
  // Code that might throw an error
} catch (error) {
  // Code to handle the error
}

Example:

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

Instead of breaking the app, the error is caught and handled gracefully.

It works like this:

  1. First, the code in try {...} is executed.

  2. If there were no errors, then catch (err) is ignored: the execution reaches the end of try and goes on, skipping catch.

  3. If an error occurs, then the try execution is stopped, and control flows to the beginning of catch (err). The err variable (we can use any name for it) will contain an error object with details about what happened.

The finally Block

The finally block runs regardless of whether an error occurred or not. It's useful for cleanup tasks like closing resources or stopping loaders.

Syntax

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

Example

try {
  console.log('Trying...');
} catch (error) {
  console.log('Error occurred');
} finally {
  console.log('Cleanup done');
}

Throwing Custom Errors

You can manually throw errors using the throw keyword. This is useful when you want to enforce certain conditions in your code.

Example

function withdraw(amount) {
  if (amount <= 0) {
    throw new Error("Amount must be greater than zero");
  }
  console.log("Withdrawal successful");
}

try {
  withdraw(-100);
} catch (error) {
  console.log(error.message);
}

You can also throw custom error types:

class CustomError extends Error {
  constructor(foo = "bar", ...params) {
    // Pass remaining arguments (including vendor specific ones) to parent constructor
    super(...params);

    // Maintains proper stack trace for where our error was thrown (non-standard)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }

    this.name = "CustomError";
    // Custom debugging information
    this.foo = foo;
    this.date = new Date();
  }
}

try {
  throw new CustomError("baz", "bazMessage");
} catch (e) {
  console.error(e.name); // CustomError
  console.error(e.foo); // baz
  console.error(e.message); // bazMessage
  console.error(e.stack); // stack trace
}

Why Error Handling Matters?

  1. Prevents Application Crashes: Without proper handling, a single error can break your entire app.

  2. Improves User Experience: Instead of showing raw error messages, you can display user-friendly feedback.

  3. Helps in Debugging: Error handling allows you to log useful information, making bugs easier to trace and fix.

  4. Enables Graceful Failure: Your app can continue functioning even when something goes wrong.

Graceful Failure Explained

Graceful failure means your application doesn't completely stop when an error occurs—it adapts.

Example

try {
  let result = riskyFunction();
  display(result);
} catch (error) {
  display("Something went wrong. Please try again.");
}

Instead of crashing, the app shows a fallback message.

Debugging Benefits

Error handling helps you:

  • Capture stack traces

  • Log meaningful error messages

  • Track down bugs faster

  • Integrate with monitoring tools (like Sentry)

Conclusion

  • Use try...catch to handle runtime errors safely

  • Use finally for cleanup tasks

  • Throw custom errors for better control and clarity

  • Always aim for graceful failure instead of crashes

  • Good error handling = better user experience + easier debugging