Node.js Error Handling Practice Questions with Solutions

Introduction

Error handling is an essential part of Node.js development. Applications can face errors because of invalid input, missing files, incorrect code, failed operations, or unexpected situations. In this chapter, you will practice handling errors using try...catch, throw, error objects, callbacks, Promises, async/await, HTTP responses, and Express error-handling middleware. Each example starts simple and gradually moves toward real-world Node.js applications. Node.js Error handling practice questions with solutions help to understand the concepts.

Question 1: How do you handle an error using try…catch?

Problem

Create a Node.js program that handles an error without crashing the application.

Solution

Create index.js:

try {
    const result = 10 / 0;

    console.log("Result:", result);

    throw new Error("Something went wrong!");
} catch (error) {
    console.log("Error:", error.message);
}

Output

Result: Infinity
Error: Something went wrong!

Step-by-Step Explanation

The try block contains code that may produce an error:

try {
    // Code that may cause an error
}

The catch block handles the error:

catch (error) {
    console.log(error.message);
}

The error variable contains information about the error.


Question 2: How do you handle an error caused by invalid JSON?

Problem

Try to convert invalid JSON into a JavaScript object and handle the error.

Solution

const jsonData = '{"name": "Rahul", age: 20}';

try {
    const student = JSON.parse(jsonData);

    console.log(student);
} catch (error) {
    console.log("Invalid JSON!");
    console.log("Error:", error.message);
}

Output

Invalid JSON!
Error: Expected property name or '}' in JSON...

The exact error message can vary by Node.js version.

Step-by-Step Explanation

JSON.parse() converts JSON text into a JavaScript value.

Valid JSON:

{
    "name": "Rahul",
    "age": 20
}

Invalid JSON:

{
    "name": "Rahul",
    age: 20
}

The age property needs double quotes.

Because invalid JSON causes JSON.parse() to throw an error, we use:

try {
    // JSON parsing
} catch (error) {
    // Handle error
}

Correct JSON

const jsonData = '{"name": "Rahul", "age": 20}';

const student = JSON.parse(jsonData);

console.log(student);

Question 3: How do you create your own error using throw?

Problem

Create a function that accepts a person’s age and throws an error if the age is below 18.

Solution

function checkAge(age) {

    if (age < 18) {
        throw new Error("Age must be 18 or above.");
    }

    return "You are eligible.";
}

try {
    console.log(checkAge(15));
} catch (error) {
    console.log("Error:", error.message);
}

Output

Error: Age must be 18 or above.

Step-by-Step Explanation

The throw statement creates an error:

throw new Error("Age must be 18 or above.");

When the condition is true, the function stops and throws the error.

The catch block receives it:

catch (error) {
    console.log(error.message);
}

Try Another Value

Change:

checkAge(15)

to:

checkAge(20)

Output:

You are eligible.

Question 4: How do you handle file system errors?

Problem

Try to read a file that does not exist and handle the error.

Solution

const fs = require("fs");

fs.readFile("missing.txt", "utf8", (error, data) => {

    if (error) {
        console.log("Unable to read the file.");
        console.log("Error:", error.message);
        return;
    }

    console.log(data);
});

Output

Unable to read the file.
Error: ENOENT: no such file or directory...

The exact message can vary by operating system and Node.js version.

Step-by-Step Explanation

Node.js uses the callback pattern for many asynchronous file system operations.

The callback receives:

(error, data)

First, check the error:

if (error) {
    console.log(error.message);
    return;
}

If there is no error, use the file data:

console.log(data);

Question 5: How do you handle errors with Promises?

Problem

Create a Promise that rejects and handle the error using .catch().

Solution

const getUser = new Promise((resolve, reject) => {

    const userFound = false;

    if (userFound) {
        resolve("User found.");
    } else {
        reject(new Error("User not found."));
    }
});

getUser
    .then((message) => {
        console.log(message);
    })
    .catch((error) => {
        console.log("Error:", error.message);
    });

Output

Error: User not found.

Step-by-Step Explanation

A Promise can:

  • Resolve successfully.
  • Reject because something went wrong.

Success:

resolve("User found.");

Error:

reject(new Error("User not found."));

The .catch() method handles the rejected Promise:

.catch((error) => {
    console.log(error.message);
});

Question 6: How do you handle errors using async/await?

Problem

Create an asynchronous function that handles a rejected Promise using try...catch.

Solution

function getUser() {

    return Promise.reject(
        new Error("User data could not be loaded.")
    );
}

async function showUser() {

    try {

        const user = await getUser();

        console.log(user);

    } catch (error) {

        console.log("Error:", error.message);
    }
}

showUser();

Output

Error: User data could not be loaded.

Step-by-Step Explanation

The function returns a rejected Promise:

return Promise.reject(
    new Error("User data could not be loaded.")
);

Because getUser() is asynchronous, we use:

await getUser();

The error is handled using:

try {
    // await operation
} catch (error) {
    // handle error
}

Question 7: How do you create a custom Error class?

Problem

Create a custom error called ValidationError for invalid user input.

Solution

class ValidationError extends Error {

    constructor(message) {
        super(message);

        this.name = "ValidationError";
    }
}

function validateUsername(username) {

    if (username.length < 3) {
        throw new ValidationError(
            "Username must contain at least 3 characters."
        );
    }

    return "Username is valid.";
}

try {

    console.log(validateUsername("AB"));

} catch (error) {

    console.log("Error Type:", error.name);
    console.log("Message:", error.message);
}

Output

Error Type: ValidationError
Message: Username must contain at least 3 characters.

Step-by-Step Explanation

We create a custom class:

class ValidationError extends Error

The class extends JavaScript’s built-in Error class.

Then:

this.name = "ValidationError";

gives the error a custom name.

Now we can throw it:

throw new ValidationError(
    "Username must contain at least 3 characters."
);

Question 8: How do you send an error response from an HTTP server?

Problem

Create a Node.js HTTP server that returns a 404 response when a requested route does not exist.

Solution

const http = require("http");

const server = http.createServer((req, res) => {

    if (req.url === "/") {

        res.writeHead(200, {
            "Content-Type": "text/plain"
        });

        res.end("Home Page");

    } else {

        res.writeHead(404, {
            "Content-Type": "text/plain"
        });

        res.end("404 - Page Not Found");
    }
});

server.listen(3000, () => {
    console.log("Server running on port 3000");
});

Output

Start the server:

node index.js

Terminal:

Server running on port 3000

Open:

http://localhost:3000/

Output:

Home Page

Open:

http://localhost:3000/about

Output:

404 - Page Not Found

Step-by-Step Explanation

First, we check the URL:

if (req.url === "/")

If it is /, return status 200:

res.writeHead(200);

For an unknown route, return:

res.writeHead(404);

The 404 status tells the client that the requested resource was not found.


Question 9: How do you handle errors in Express using error-handling middleware?

Problem

Create an Express application that throws an error and handles it using error-handling middleware.

Solution

Install Express:

npm install express

Create index.js:

const express = require("express");

const app = express();

app.get("/", (req, res) => {
    res.send("Home Page");
});

app.get("/error", (req, res) => {

    throw new Error("Something went wrong!");
});

app.use((error, req, res, next) => {

    console.error(error.message);

    res.status(500).json({
        error: "Internal Server Error"
    });
});

app.listen(3000, () => {
    console.log("Server running on port 3000");
});

Run:

node index.js

Open:

http://localhost:3000/error

Output

{
    "error": "Internal Server Error"
}

Step-by-Step Explanation

The route creates an error:

throw new Error("Something went wrong!");

The error-handling middleware is:

app.use((error, req, res, next) => {
    // Handle error
});

Notice that it has four parameters:

(error, req, res, next)

This is how Express recognizes error-handling middleware.

Question 10: How do you build a complete error-handling system in Node.js?

Problem

Create an Express API that:

  • Validates user input.
  • Handles missing users.
  • Uses custom errors.
  • Returns proper HTTP status codes.
  • Handles unexpected errors using middleware.

Solution

Install Express:

npm install express

Create index.js:

const express = require("express");

const app = express();

app.use(express.json());

class AppError extends Error {

    constructor(message, statusCode) {

        super(message);

        this.statusCode = statusCode;
        this.name = "AppError";
    }
}

const users = [
    {
        id: 1,
        name: "Rahul"
    },
    {
        id: 2,
        name: "Priya"
    }
];

app.get("/users/:id", (req, res, next) => {

    try {

        const id = Number(req.params.id);

        if (Number.isNaN(id)) {

            throw new AppError(
                "User ID must be a number.",
                400
            );
        }

        const user = users.find(
            (user) => user.id === id
        );

        if (!user) {

            throw new AppError(
                "User not found.",
                404
            );
        }

        res.json(user);

    } catch (error) {

        next(error);
    }
});

app.use((error, req, res, next) => {

    console.error(error);

    const statusCode = error.statusCode || 500;

    res.status(statusCode).json({
        success: false,
        error: error.message || "Internal Server Error"
    });
});

app.listen(3000, () => {

    console.log(
        "Server running on http://localhost:3000"
    );
});

Step-by-Step Explanation

Step 1: Create a custom error

class AppError extends Error

This allows us to store an HTTP status code along with the error message.

Step 2: Create sample users

const users = [
    {
        id: 1,
        name: "Rahul"
    },
    {
        id: 2,
        name: "Priya"
    }
];

Step 3: Create the API route

app.get("/users/:id", ...)

The :id represents a dynamic URL parameter.

Step 4: Convert the ID to a number

const id = Number(req.params.id);

Step 5: Validate the ID

if (Number.isNaN(id))

If the ID is not a number, throw a 400 error.

Step 6: Find the user

const user = users.find(
    (user) => user.id === id
);

Step 7: Handle a missing user

if (!user) {
    throw new AppError(
        "User not found.",
        404
    );
}

Step 8: Pass errors to middleware

catch (error) {
    next(error);
}

Step 9: Handle errors centrally

app.use((error, req, res, next) => {
    // Error handling
});

HTTP status:

{
    "success": false,
    "error": "User ID must be a number."
}

HTTP status:

400

Key Takeaways

  • Errors are a normal part of application development.
  • try...catch handles synchronous JavaScript exceptions.
  • throw allows you to create your own errors.
  • new Error() creates a standard Error object.
  • error.message contains the error message.
  • error.name identifies the error type.
  • Node.js callback APIs commonly use the error-first callback pattern.
  • Always check the error argument before using callback results.
  • Promise rejections can be handled using .catch().
  • async/await errors can commonly be handled with try...catch.
  • Custom error classes can represent specific types of application errors.
  • HTTP status codes communicate the result of a request to the client.
  • 404 commonly means a requested resource was not found.
  • 400 commonly indicates an invalid client request.
  • 500 commonly indicates an unexpected server-side error.
  • Express uses four-argument middleware for error handling:
(error, req, res, next)
  • Centralized error-handling middleware keeps Express applications easier to maintain.
  • Do not expose sensitive internal error details to users in production.
  • Log useful diagnostic information on the server while returning safe messages to clients.
  • Validate user input before processing it.
  • Good error handling makes Node.js applications more reliable and easier to debug.

FAQs

1. What is error handling in Node.js?

Error handling is the process of detecting, managing, and responding to problems that occur while a Node.js application is running.

Common techniques include:

try...catch
throw
Promise.catch()
async/await with try...catch
callback error handling
Express error middleware

2. What is try…catch in Node.js?

try...catch allows you to handle exceptions without allowing the error to terminate the current synchronous operation unexpectedly.

Example:

try {
    JSON.parse("invalid json");
} catch (error) {
    console.log(error.message);
}

The try block contains risky code, while catch handles the error.

3. What is the purpose of throw in JavaScript?

throw allows you to create and send an error to the nearest appropriate error handler.

Example:

if (age < 18) {
    throw new Error("Age must be 18 or above.");
}

The error can then be handled using try...catch.

4. How do you handle errors in a Node.js callback?

Node.js callback-based APIs commonly use the error-first pattern:

fs.readFile("file.txt", "utf8", (error, data) => {

    if (error) {
        console.log(error.message);
        return;
    }

    console.log(data);
});

Always check the error argument before using the returned data.

5. How do you handle errors with async/await?

Use try...catch around the asynchronous operation:

async function getData() {

    try {

        const data = await fetchData();

        console.log(data);

    } catch (error) {

        console.log(error.message);
    }
}

This catches errors caused by a rejected Promise.

6. How does Express handle errors?

Express applications can use error-handling middleware.

Example:

app.use((error, req, res, next) => {

    res.status(500).json({
        error: "Something went wrong."
    });
});

Express recognizes this middleware because it has four parameters:

(error, req, res, next)

7. What HTTP status code should be used for server errors?

A 500 status code is commonly used when the server encounters an unexpected condition.

For example:

res.status(500).json({
    error: "Internal Server Error"
});

Other common status codes include:

400 → Bad Request
401 → Unauthorized
403 → Forbidden
404 → Not Found
500 → Internal Server Error

Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.

Scroll to Top