# Error Handling in JavaScript: Try, Catch, Finally

Introduction

During software building, or we can say the coding process, one of the most important and skill full part is error-handling. No matter how well an application is written, errors can still happen during execution. A user may enter invalid data, an API request may fail, a file may not exist, or unexpected values may break the logic of the application.

If errors are not handled properly, applications can crash, freeze, or behave unpredictably. Good error handling helps developers prevent these problems and makes applications more stable and reliable.

JavaScript provides built-in mechanisms such as `try`, `catch`, `finally`, and `throw` to manage runtime errors properly.

### What Are Errors in JavaScript?

An error occurs in JavaScript when the engine can't execute the code successfully. When JavaScript finds an issue that it cannot handle automatically, it throws an error object & if the error is not handled properly, it stops execution.

Example:

```javascript
console.log(userName);
```

Output:

```plaintext
ReferenceError: userName is not defined
```

In this example, JavaScript throws a `ReferenceError` because the variable does not exist.

### Types of Errors in JavaScript

JavaScript includes multiple built-in error types. Each type represents a different category of problem.

### ReferenceError

A `ReferenceError` occurs when code tries to access a variable that has not been declared.

Example:

```javascript
console.log(totalAmount);
```

Output:

```plaintext
ReferenceError: totalAmount is not defined
```

This error usually happens due to a misspelled variable name, a variable outside scope, use variable before declaration.

### TypeError

A `TypeError` happens when an operation is performed on an incompatible value.

Example:

```javascript
const number = 100;

number.toUpperCase();
```

Output:

```javascript
TypeError: number.toUpperCase is not a function
```

Here, `toUpperCase()` works only on strings, not numbers.

Common causes of `TypeError` include:

*   Calling methods on incorrect data types
    
*   Accessing properties of `undefined`
    
*   Using array methods on non-arrays
    

### SyntaxError

A `SyntaxError` occurs when the structure of the code is invalid.

Example:

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

Output:

```javascript
SyntaxError: Unexpected token '{'
```

JavaScript cannot execute code with invalid syntax because it fails during parsing.

Common reasons include:

*   Missing brackets
    
*   Missing commas
    
*   Incorrect operators
    
*   Invalid JavaScript structure
    

### RangeError

A `RangeError` occurs when a value goes outside the allowed range.

Example:

```javascript
const items = new Array(-2);
```

Output:

```plaintext
RangeError: Invalid array length
```

This error usually happens when:

*   Array lengths become invalid
    
*   Recursive functions exceed limits
    
*   Numeric values go outside accepted boundaries
    

### URIError

A `URIError` occurs when URI-related functions receive invalid input.

Example:

```javascript
decodeURIComponent("%");
```

Output:

```plaintext
URIError: URI malformed
```

This type of error is less common but can happen while working with URLs or encoded data.

### Why Error Handling Is Important

Error handling is important because real-world applications constantly deal with unpredictable situations.

Without proper handling:

*   Applications may crash
    
*   Users may lose data
    
*   Systems may become unstable
    
*   Debugging becomes difficult
    

### Improves User Experience

Users should never see broken screens or confusing crashes.

Instead of crashing completely, applications should display meaningful messages.

Example:

```javascript
try {
  const response = JSON.parse(invalidData);
} catch (error) {
  console.log("Unable to process data");
}
```

This keeps the application running even when invalid data appears.

### Makes Debugging Easier

Errors provide details about:

*   What went wrong
    
*   Where the issue occurred
    
*   Which line caused the problem
    

Example:

```plaintext
TypeError: Cannot read properties of undefined
```

This information helps developers fix issues faster.

### Prevents Invalid Data

Sometimes invalid values can spread through an application silently.

Example:

```javascript
const result = Number("abc");

console.log(result);
```

Output:

```plaintext
NaN
```

If this value continues into calculations or databases, it may create larger problems later.

Error handling allows developers to stop invalid operations early.

### Improves Application Stability

Applications that handle failures gracefully are more reliable.

Even if one operation fails, the rest of the system can continue working normally.

This is especially important in:

*   Banking systems
    
*   Payment gateways
    
*   Authentication systems
    
*   APIs
    
*   Database applications
    

### The `try...catch` Statement

JavaScript provides the `try...catch` statement to handle runtime errors.

The `try` block contains code that may fail.

The `catch` block handles errors if they occur.

Syntax:

```javascript
try {
  // risky code
} catch (error) {
  // error handling
}
```

### Example of `try...catch`

```javascript
try {
  const user = JSON.parse("{name:'Pallab'}");

  console.log(user);
} catch (error) {
  console.log("Invalid JSON format");
}
```

Output:

```plaintext
Invalid JSON format
```

### Understanding the Error Object

The `catch` block receives an error object.

This object contains useful information about the error.

Example:

```javascript
try {
  const data = JSON.parse("invalid json");
} catch (error) {
  console.log(error.name);
  console.log(error.message);
}
```

Output:

```plaintext
SyntaxError
Unexpected token i in JSON at position 0
```

### The `finally` Block

The `finally` block always executes whether an error occurs or not.

It is mainly used for cleanup operations.

Syntax:

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

### Example of `finally`

```javascript
try {
  console.log("Connecting to database");
} catch (error) {
  console.log("Database error");
} finally {
  console.log("Closing database connection");
}
```

Output:

```plaintext
Connecting to database
Closing database connection
```

### Throwing Custom Errors

JavaScript also allows developers to create custom errors using the `throw` keyword.

This is useful when application-specific rules need validation.

Syntax:

```javascript
throw new Error("Message");
```

### Example of Custom Error

```javascript
function registerUser(age) {
  if (age < 18) {
    throw new Error("User must be at least 18 years old");
  }

  return "Registration successful";
}

try {
  console.log(registerUser(15));
} catch (error) {
  console.log(error.message);
}
```

Output:

```javascript
User must be at least 18 years old
```

Here, JavaScript itself sees no technical problem, but the application logic requires age validation.

### Creating Custom Error Classes

Developers can also create their own error classes.

Example:

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

throw new ValidationError("Invalid email address");
```

Custom error classes help organize large applications more effectively.

### Nested `try...catch`

JavaScript allows nested error handling.

Example:

```javascript
try {
  try {
    JSON.parse("invalid");
  } catch (error) {
    console.log("Inner catch block");
  }
} catch (error) {
  console.log("Outer catch block");
}
```

This is useful in complex applications where different layers handle different errors.

### Error Handling in Async Code

Errors can also happen in asynchronous operations.

For async functions, `try...catch` it works together with `async/await`.

Example:

```javascript
async function fetchData() {
  try {
    const response = await fetch("https://api.example.com/data");

    const data = await response.json();

    console.log(data);
  } catch (error) {
    console.log("Failed to fetch data");
  }
}
```

This helps handle API failures safely.

## Best Practices for Error Handling

### **Handle Errors Properly**

Never ignore errors completely.

Bad practice:

```javascript
catch (error) {

}
```

Always log or handle errors meaningfully.

### Use Specific Error Messages

Good error messages make debugging easier.

Bad:

```javascript
throw new Error("Something went wrong");
```

Better:

```javascript
throw new Error("Password must contain at least 8 characters");
```

### Avoid Exposing Sensitive Information

Do not show internal server details directly to users.

Bad:

```javascript
Database connection failed at port 3306
```

Better:

```javascript
Unable to process request right now
```

### Use `finally` for Cleanup

Always clean resources properly.

Example:

```javascript
finally {
  connection.close();
}
```

### Conclusion

Error handling is a core part of JavaScript development. Applications cannot rely on everything working all the time perfectly. Failures are normal in software systems, and handling them properly is what makes applications reliable.
