Lesson 26 of 50 – Error Handling

52% Completed
52%

Error Handling in Node.js

Error handling helps us identify and manage problems in a program. It prevents unexpected failures and helps us display useful messages when something goes wrong.

Remember: Errors can occur because of invalid input, missing files, network problems, or mistakes in code. Node.js provides several ways to detect and handle these errors.

1. What Is an Error?

An error is a problem that occurs while a program is being written or executed. Different types of errors require different solutions.

Error Type Meaning Example
Syntax Error Code does not follow JavaScript syntax rules. if (x > 5 { }
Reference Error A variable or identifier is not available. console.log(unknownVariable);
Type Error An operation is used with an incompatible value. null.name
Range Error A value is outside an allowed range. new Array(-1)
Custom Error An application creates its own error. throw new Error("Invalid input");

2. Using try...catch

The try...catch statement allows us to handle errors instead of letting them interrupt the normal flow of the program.

Example: Basic try...catch
try {
    console.log(unknownVariable);
} catch (error) {
    console.log("An error occurred");
}

console.log("Program continues");
Output:
An error occurred
Program continues

The undefined variable causes a ReferenceError. The catch block handles it, allowing the program to continue.

3. Understanding the Error Object

JavaScript errors usually provide useful properties such as name and message. The stack property can also help developers locate where an error occurred.

Example: Display Error Details
try {
    throw new Error("Something went wrong");
} catch (error) {
    console.log("Name:", error.name);
    console.log("Message:", error.message);
}
Output:
Name: Error
Message: Something went wrong

The error.message property contains the descriptive message supplied when the Error object was created.

4. Using throw

The throw statement lets us create an error when a condition is not valid.

Example: Validate Age
function checkAge(age) {
    if (age < 18) {
        throw new Error("You must be at least 18");
    }

    return "Access allowed";
}

try {
    console.log(checkAge(16));
} catch (error) {
    console.log(error.message);
}
Output:
You must be at least 18

When the age is below 18, the function throws an error. The surrounding catch block handles it.

5. Using finally

The finally block runs after the try/catch process, whether an error occurs or not. It is useful for cleanup operations.

Example: try...catch...finally
try {
    console.log("Starting program");

    throw new Error("Something failed");
} catch (error) {
    console.log("Error:", error.message);
} finally {
    console.log("Program finished");
}
Output:
Starting program
Error: Something failed
Program finished

6. Handling Errors in Asynchronous Code

Errors in asynchronous code need appropriate handling. When using async and await, wrap awaited operations in try...catch to handle rejected Promises.

Example: Async Error Handling
function getData() {
    return new Promise(function(resolve, reject) {
        reject(new Error("Unable to get data"));
    });
}

async function showData() {
    try {
        const data = await getData();
        console.log(data);
    } catch (error) {
        console.log("Error:", error.message);
    }
}

showData();
Output:
Error: Unable to get data

The rejected Promise causes the await expression to throw. The catch block handles the error.

7. Handling File System Errors

When working with files, errors may occur if a file does not exist or the program does not have permission to access it. Node.js provides callback-based and Promise-based file system APIs.

Example: Reading a File with a Callback
const fs = require("fs");

fs.readFile("student.txt", "utf8", function(error, data) {
    if (error) {
        console.log("Unable to read file:", error.message);
        return;
    }

    console.log(data);
});

Save this code in a JavaScript file and run it with Node.js. If student.txt is missing or cannot be read, the error is handled by the callback.

Always check the error argument before using the file data. Do not assume that an asynchronous operation succeeded.

8. Creating a Custom Error

You can create your own error class when an application needs errors with specific names or additional information.

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

function registerUser(username) {
    if (!username) {
        throw new ValidationError("Username is required");
    }

    return "User registered";
}

try {
    console.log(registerUser(""));
} catch (error) {
    if (error instanceof ValidationError) {
        console.log(error.name + ":", error.message);
    } else {
        console.log("Unexpected error:", error.message);
    }
}
Output:
ValidationError: Username is required

9. Best Practices for Error Handling

Good Practices
  • Use try...catch for errors that can be handled locally.
  • Check errors in callback-based asynchronous APIs.
  • Handle rejected Promises with catch or try...catch.
  • Use clear, meaningful error messages.
  • Validate user input before processing it.
  • Use finally for cleanup when appropriate.
  • Avoid exposing passwords, tokens, or sensitive details in error messages.
  • Log useful debugging information securely.
Important: A try...catch block does not automatically catch errors thrown later inside an unrelated asynchronous callback. Handle errors inside the callback or use a Promise-based API with appropriate rejection handling.

10. Practical Assignment

Practice these programs:
  1. Write a program that uses try...catch.
  2. Create an Error object and display its name and message.
  3. Throw an error when a student's marks are below zero.
  4. Use finally to display "Program completed".
  5. Handle a rejected Promise using async and await.
  6. Read a file and handle the error if it does not exist.
  7. Create a custom ValidationError class.

Test Your Knowledge – Error Handling

Select the correct answer for each question.

1. Which statement is used to generate an error manually?
2. Which block is used to handle an error in try...catch?
3. What is the purpose of the finally block?