Skip to content

Session 7

Javascript Error Handling

Updated View as Markdown

During script execution, errors are inevitable. They can stem from syntax mistakes, invalid user input, network failures, or unforeseen runtime conditions. Without proper error handling, a single failure can crash an entire application or leave users with broken interfaces. This session introduces JavaScript’s structured error-handling mechanisms, enabling developers to gracefully catch, diagnose, and recover from runtime exceptions while keeping applications stable and user-friendly.

Objectives

Do not copy. Read for understanding and the viva
  • Understand the try...catch...finally execution flow
  • Implement custom error throwing using the throw statement
  • Utilize JavaScript’s built-in Error object to diagnose failures
  • Apply nested try...catch blocks for complex validation scenarios
  • Practice robust error handling through hands-on lab exercises

Error Handling Syntax

JavaScript uses a structured block system to manage exceptions:

try {
  // Code that might throw an error
} catch(error) {
  // Executes ONLY if an error occurs in try
  // `error` is an instance of the built-in Error object
} finally {
  // ALWAYS executes, regardless of success or failure
  // Ideal for cleanup, closing connections, resetting UI
}

Execution Flow

  1. try block runs.
  2. If no error → skips catch → runs finally.
  3. If error occurs → jumps to catch → runs catch → runs finally.

The throw Statement

Allows you to create custom errors or re-throw caught errors:

throw "Email cannot be empty";      // Throws a string
throw 404;                          // Throws a number
throw new Error("Custom validation failed"); // Throws an Error object (recommended)

Built-in Error Object

When an error is caught, JavaScript provides an error object with two key properties:

PropertyDescription
error.nameType of error (e.g., “TypeError”, “ReferenceError”)
error.messageHuman-readable description of what went wrong

Error Types

Error NameTrigger Condition
SyntaxErrorInvalid JS syntax (e.g., missing brackets, 2 = x)
ReferenceErrorAccessing an undeclared variable
TypeErrorInvalid operation on a value type (e.g., “abc”.toUpperCase on undefined)
RangeErrorNumber outside valid range (e.g., invalid array length)
EvalErrorError inside eval() function
URIErrorMalformed URI in encoding/decoding functions

Nested try...catch Blocks

For complex validation, you can nest blocks to handle errors at different levels:

try {
  // Outer validation
  try {
    // Inner risky operation
    JSON.parse(invalidJSON);
  } catch(innerErr) {
    console.warn("Inner failed:", innerErr.message);
    throw new Error("Data parsing failed"); // Re-throw to outer catch
  }
} catch(outerErr) {
  console.error("Outer caught:", outerErr.message);
} finally {
  console.log("Cleanup complete");
}

Best Practices & Common Pitfalls

Do not copy. Read for understanding and the viva
PitfallBest Practice
Empty catch {} blocksAlways log or handle the error; never silently swallow failures
Throwing non-Error valuesUse throw new Error(“msg”) for consistent stack traces
Overusing try…catch for control flowUse conditionals (if/else) for expected logic; reserve try…catch for true exceptions
Ignoring finally for cleanupUse finally to reset UI states, close streams, or hide loading spinners
Assuming all errors are recoverableSome errors (e.g., SyntaxError) should be fixed at development time, not caught at runtime

Quick Guide

Do not copy. Read for understanding and the viva
// 🔍 Basic Error Handling
try { riskyOperation(); }
catch(err) { console.error(err.name, err.message); }
finally { console.log("Runs no matter what"); }

// 🚀 Custom Error
if (!userInput) throw new TypeError("Input is missing");

// 🔄 Retry Logic (Lab Exercise 4 pattern)
function safeMultiply(a, b) {
  while (true) {
    try { return primitiveMultiply(a, b); }
    catch (e) { if (e instanceof MultiplicatorUnitFailure) continue; else throw e; }
  }
}

Question 1

Problem Statement

Write in lab record

Write an HTML code using JavaScript to add two numbers taken as input from user and display the result of division operation on them i.e. a/b. If an error occurs, show the error. Use error handling concepts in JavaScript.

Preview

Do not copy. Read for understanding and the viva

Divide a / b

Waiting for input...

Code

Write in lab record
add-division.htmlhtml
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Ex1: Division Error Handling</title>
        <style>
            body {
                font-family: sans-serif;
                padding: 20px;
                max-width: 400px;
            }
        </style>
    </head>
    <body>
        <h2>Divide a / b</h2>
        <input
            id="numA"
            type="number"
            placeholder="Number a"
            style="width: 100%; margin-bottom: 8px; padding: 5px"
        />
        <input
            id="numB"
            type="number"
            placeholder="Number b"
            style="width: 100%; margin-bottom: 8px; padding: 5px"
        />
        <button id="calcBtn" style="padding: 8px 16px">Calculate</button>
        <p id="output" style="margin-top: 10px; font-weight: bold"></p>

        <script>
            document.getElementById("calcBtn").addEventListener("click", () => {
                try {
                    const a = parseFloat(document.getElementById("numA").value);
                    const b = parseFloat(document.getElementById("numB").value);

                    if (isNaN(a) || isNaN(b))
                        throw new TypeError(
                            "Both fields must be valid numbers.",
                        );
                    if (b === 0)
                        throw new RangeError("Division by zero is undefined.");

                    document.getElementById("output").textContent =
                        `Result: ${a / b}`;
                } catch (err) {
                    document.getElementById("output").textContent =
                        `❌ Error (${err.name}): ${err.message}`;
                }
            });
        </script>
    </body>
</html>

HTML View

Open in new tab ↗

Question 2

Problem Statement

Write in lab record

A teacher has created a gradeLabs function that verifies if student programming labs work. This function loops over an array of JavaScript objects that should contain a student property and runLab property. The runLab property is expected to be a function containing the student’s code. The runLab function is called and the result is compared to the expected result. If the result and expected result don’t match, then the lab is considered a failure.

Demo

Do not copy. Read for understanding and the viva

Auto-Grader

Code

Write in lab record
grade-lab.htmlhtml
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Ex2: Grade Labs</title>
        <style>
            body {
                font-family: sans-serif;
                padding: 20px;
            }
            pre {
                background: #f4f4f4;
                padding: 10px;
                border-radius: 5px;
            }
        </style>
    </head>
    <body>
        <h2>Auto-Grader</h2>
        <button id="gradeBtn">Run gradeLabs()</button>
        <pre id="results"></pre>

        <script>
            const students = [
                { name: "Alice", runLab: () => 2 + 2, expected: 4 },
                {
                    name: "Bob",
                    runLab: () => {
                        throw new ReferenceError("x is not defined");
                    },
                    expected: 5,
                },
                { name: "Charlie", runLab: () => 10 / 2, expected: 6 }, // Wrong result
                { name: "Diana", runLab: () => "5" * 2, expected: 10 }, // Type coercion success
            ];

            function gradeLabs(students) {
                let logs = [];
                for (const s of students) {
                    try {
                        const actual = s.runLab();
                        if (actual === s.expected)
                            logs.push(`✅ ${s.name}: PASS`);
                        else
                            logs.push(
                                `❌ ${s.name}: FAIL (Got ${actual}, Expected ${s.expected})`,
                            );
                    } catch (err) {
                        logs.push(
                            `⚠️ ${s.name}: EXCEPTION - ${err.name}: ${err.message}`,
                        );
                    }
                }
                return logs.join("\n");
            }

            document
                .getElementById("gradeBtn")
                .addEventListener("click", () => {
                    document.getElementById("results").textContent =
                        gradeLabs(students);
                });
        </script>
    </body>
</html>

HTML View

Open in new tab ↗

Question 3

Problem Statement

Write in lab record

There is an array of animals. The user is asked to enter the index for the animal they want to see.

  1. If the user enters an index that does NOT contain an animal, the code will throw a TypeError when name is referenced on an undefined value.
  2. Update the above program to print out the index the user entered. We want this message to be printed EVERY time the code runs

Demo

Do not copy. Read for understanding and the viva

Animal Lookup

Code

Write in lab record
animals.htmlhtml
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Ex3: Animal Lookup</title>
        <style>
            body {
                font-family: sans-serif;
                padding: 20px;
            }
            input,
            button {
                padding: 8px;
                margin-right: 5px;
            }
        </style>
    </head>
    <body>
        <h2>Animal Lookup</h2>
        <input id="idxInput" type="number" placeholder="Enter index (0-2)" />
        <button id="lookupBtn">Find Animal</button>
        <p id="animalRes" style="margin-top: 10px; font-weight: bold"></p>
        <p id="finallyMsg" style="color: #555"></p>

        <script>
            const animals = [
                { id: 0, name: "Lion" },
                { id: 1, name: "Elephant" },
                { id: 2, name: "Tiger" },
            ];

            document
                .getElementById("lookupBtn")
                .addEventListener("click", () => {
                    const idx = parseInt(
                        document.getElementById("idxInput").value,
                    );
                    let animalName = "";

                    try {
                        const animal = animals[idx];
                        if (!animal)
                            throw new TypeError(
                                `Index ${idx} does not contain an animal.`,
                            );
                        animalName = animal.name;
                        document.getElementById("animalRes").textContent =
                            `🦁 Animal: ${animalName}`;
                    } catch (err) {
                        document.getElementById("animalRes").textContent =
                            `❌ ${err.message}`;
                    } finally {
                        document.getElementById("finallyMsg").textContent =
                            `📝 Checked index: ${idx} (Executed via finally)`;
                    }
                });
        </script>
    </body>
</html>

HTML View

Open in new tab ↗

Question 4

Problem Statement

Write in lab record

Assume you have a function primitiveMultiply that in 20 percent of cases multiplies two numbers and in the other 80 percent of cases raises an exception of type MultiplicatorUnitFailure. Write a function that wraps this clunky function and just keeps trying until a call succeeds, after which it returns the result. Make sure you handle only the exceptions you are trying to handle.

Demo

Do not copy. Read for understanding and the viva

Reliable Multiply

Input: 6 × 7 (20% success rate per attempt)

Code

Write in lab record
primitive-multiplyn.htmlhtml
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Ex4: Retry Multiplication</title>
        <style>
            body {
                font-family: sans-serif;
                padding: 20px;
            }
            button {
                padding: 10px 20px;
            }
        </style>
    </head>
    <body>
        <h2>Reliable Multiply</h2>
        <p>Input: <strong>6 × 7</strong></p>
        <button id="multiplyBtn">Run Wrapper</button>
        <p id="res" style="margin-top: 10px; font-weight: bold"></p>

        <script>
            class MultiplicatorUnitFailure extends Error {
                constructor(msg) {
                    super(msg);
                    this.name = "MultiplicatorUnitFailure";
                }
            }

            function primitiveMultiply(a, b) {
                if (Math.random() < 0.2) return a * b;
                else
                    throw new MultiplicatorUnitFailure(
                        "Random failure (80% chance)",
                    );
            }

            function reliableMultiply(a, b) {
                let attempts = 0;
                while (true) {
                    attempts++;
                    try {
                        return { result: primitiveMultiply(a, b), attempts };
                    } catch (e) {
                        if (!(e instanceof MultiplicatorUnitFailure)) throw e; // Re-throw unknown errors
                    }
                }
            }

            document
                .getElementById("multiplyBtn")
                .addEventListener("click", () => {
                    const { result, attempts } = reliableMultiply(6, 7);
                    document.getElementById("res").textContent =
                        `✅ Result: ${result} (Took ${attempts} attempt${attempts > 1 ? "s" : ""})`;
                });
        </script>
    </body>
</html>

HTML View

Open in new tab ↗
Navigation

Type to search…

↑↓ navigate↵ selectEsc close