Error handling in JavaScript

- 👤 Andrés Cruz

🇪🇸 En español

Error handling in JavaScript

When we develop a JavaScript application, there is something that will always happen sooner or later: errors. They can appear due to bugs in our code, unexpected user input, or incorrect API responses. In my experience, a good application is not one that never fails, but one that knows how to handle errors in a clear and controlled way, showing useful messages and preventing everything from breaking.

In this guide, I am going to explain how error handling works in JavaScript, from the very basics to real-world cases you will encounter in actual projects, with clear examples and best practices.

What are errors in JavaScript and why do they occur?

An error in JavaScript is a situation that prevents the program from executing correctly. When it occurs, the JavaScript engine stops normal execution and generates an Error object with information about what failed.

In practice, errors usually appear for two major reasons:

Programmer errors vs. user errors

  • Programmer errors: misspelled variables, non-existent functions, syntax errors, incorrect types, etc.
  • User or environment errors: poorly entered data, incomplete forms, malformed JSON, network failures, unexpected API responses.

User errors should be anticipated and handled, while programming errors should help us debug and improve the code.

JavaScript error types you should know

JavaScript includes several built-in error types. Knowing them will help you quickly identify what is failing.

ReferenceError, TypeError, and SyntaxError

The most common ones are:

  • ReferenceError: occurs when you try to use a variable that does not exist.
    • console.log(nonExistentVariable);
  • TypeError: appears when you use a value of an incorrect type.
    • let num = null; 
      num.toFixed(2);
  • SyntaxError: occurs when the code does not have valid syntax.
    • let x = ;

Common errors in real applications

In real applications, it is very common to encounter:

  • Accessing properties of undefined or null
  • Processing incorrect JSON
  • Calling methods that do not exist
  • Handling asynchronous data that has not yet arrived

That is why error handling is not optional: it is part of the application design.

How try…catch works in JavaScript

To handle JavaScript errors, use try and catch. Writing try-catch code to handle an error looks like this:

try {
    // code
} catch (error) {
    // error handling
}

First, the try block is executed:

  • If no error occurs, the catch block is ignored.
  • If an error occurs, the execution of the try block stops and passes directly to the catch block.
try {
    console.log("first blok try");
    console.log("last blok try");
} catch (error) {
    console.log("No error occurs, then this code is ignored");
}
 
/* output
first blok try
last blok try
*/

The code in the try block above will not return an error, so the code in the catch block will be ignored and will not execute.

What happens when an error occurs inside the try block:

The following is an example of code that generates an error:

try {
    console.log("First blok try");   // (1)
    errorCode;                      // (2)
    console.log("Last blok try");  // (3)
} catch (error) {
    console.log("An error occurred!");  // (4)
}
 
/* output
First blok try
An error occurred!
*/

The line of code (2) will produce an error. Execution of the code within the try block will stop, so line (3) will not execute. Then, the code will continue to line (4) or the catch block.

Now consider the catch block. The catch has a parameter called error (the variable name can be changed). An error variable is an object that stores detailed information about the error that occurred.

The error object has several main properties, namely:

  • name: The name of the error that occurred.
  • message: Message regarding the details of the error.
  • stack: Information about the sequence of events that caused the error. It is generally used for debugging because it contains information about which line caused the error.

Now let's try to modify the code and display the error properties above.

try {
    console.log("First blok try");   // (1)
    errorCode;                      // (2)
    console.log("Last blok try");  // (3)
} catch (error) {
    console.log(error.name);
    console.log(error.message);
    console.log(error.stack);
}
 
/* output
Awal blok try
ReferenceError
errorCode is not defined
ReferenceError: errorCode is not defined
    at file:///home/dicoding/Playground/javascript/CoffeeMachine/error.js:3:5
    at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
    at async Loader.import (internal/modules/esm/loader.js:166:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)
*/

From the information above, we can see that the error that appears is a ReferenceError because errorCode is considered an undefined variable or value.

try…catch…finally: when and why to use finally

In addition to try and catch, there is one more block in the JavaScript error handling mechanism, which is finally. The finally block will always run regardless of the result of the try-catch block.

try {
    console.log("First blok try");
    console.log("Last blok try");
} catch (error) {
    console.log("This line is ignored");
} finally {
    console.log("Will still be executed");
}
 
/* output
First blok try
Last blok try
Will still be executed
*/

The finally block is always executed, whether there is an error or not. It is especially useful for:

  • Closing connections
  • Releasing resources
  • Displaying final messages
  • Measuring execution times

Even if there is a return or a throw, finally will execute beforehand.

Throwing custom errors with throw

There are situations where the code does not fail on its own, but logically something is wrong. In those cases, we can throw our own errors using throw.

Error handling in JSON and APIs

let json = '{ "name": "Johon", "age": 20 }';
 
try {
    let user = JSON.parse(json);
 
    console.log(user.name);
    console.log(user.age);
} catch (error) {
    console.log(error.name);
    console.log(error.message);
}

In the code above, the JSON.parse function will parse or convert the JSON variable (String) into an object. We will encounter many scenarios like this when making API requests.

Run the code above in your text editor. The application should work smoothly without causing errors.

So, what happens if the JSON string does not match the JavaScript object format?

try {
    let user = JSON.parse(json);
 
    console.log(user.name);
    console.log(user.age);
} catch (error) {
    console.log(error.name);
    console.log(error.message);
}
 
 
/* output
SyntaxError
Unexpected token b in JSON at position 2
*/

If the JSON does not match the format, JSON.parse will throw an error. The catch block will detect the error, and the code within it will be executed.

Error handling in promises and async/await

With asynchronous code, error handling changes slightly.

.catch() vs try…catch in async functions

With promises:

fetch(url)
 .then(res => res.json())
 .catch(error => console.log(error));


With async/await:

async function getData() {
 try {
   const res = await fetch(url);
   const data = await res.json();
   console.log(data);
 } catch (error) {
   console.log("Error in the request");
 }
}

Personally, I prefer async/await with try...catch because the code is more linear and easier to read, especially as logic grows.

Best practices for error handling in JavaScript

  • After working with many errors (more than I would like to admit), these are some key practices:
  • Clear messages for the user
    • Do not show technical messages like “TypeError: undefined is not a function”.
      Translate the error into something understandable: “A problem occurred while processing the data.”
  • Silent errors vs. critical errors
    • Critical errors → notify the user
    • Minor errors → log and continue
  • Also, avoid empty catch blocks. If you catch an error, do something with it, even if it is just logging it.

Frequently asked questions about error handling in JavaScript

  • What is error handling in JavaScript?
    • It is the set of techniques to detect, control, and respond to errors without the application failing.
  • What is try…catch for?
    • It allows catching execution errors and managing the program flow when something fails.
  • What is the difference between an error and an exception?
    • An error is the object; an exception is that error when it is thrown with throw.
  • How to handle errors in asynchronous code?
    • Using .catch() in promises or try...catch inside async functions.

Conclusion

Error handling in JavaScript is not just a technical issue, but an essential part of the user experience. Instead of avoiding errors, we must anticipate them, control them, and communicate what is happening clearly. When you well understand try...catch, throw, and the Error object, your applications become much more robust and professional.

I agree to receive announcements of interest about this Blog.

We will see how to handle errors in JavaScript through the try catch and some possible variants; Handling errors in projects is a fundamental task for the good flow of the application.

| 👤 Andrés Cruz

🇪🇸 En español