HomeGuidesJavaScriptJavaScript Error Handling — try/catch, Custom Errors & Async Patterns
JavaScript

JavaScript Error Handling: try/catch, Custom Errors, and Async Errors

Error handling is essential for production code. Here's what interviews test — from try/catch to handling async errors properly.

Examifyr·2026·5 min read

try/catch/finally

try executes code. catch handles errors. finally always runs.

try {
    const data = JSON.parse("invalid json");
} catch (error) {
    console.error(error.name);     // "SyntaxError"
    console.error(error.message);  // "Unexpected token..."
} finally {
    console.log("always runs");    // cleanup here
}

// Rethrowing:
try {
    riskyOperation();
} catch (error) {
    if (error instanceof NetworkError) {
        handle(error);
    } else {
        throw error;  // rethrow unknown errors
    }
}

Error types

JavaScript has built-in error types. Know them for interviews.

new Error("generic error");
new TypeError("wrong type");           // wrong type used
new ReferenceError("not defined");     // undefined variable
new SyntaxError("invalid syntax");     // parse error
new RangeError("out of range");        // number out of range
new URIError("bad URI");

// Checking type:
try { null.property }
catch (e) {
    e instanceof TypeError;  // true
    e.name;                  // "TypeError"
    e.message;               // description
    e.stack;                 // stack trace
}

Custom error classes

Extend Error to create domain-specific error types.

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

class NetworkError extends Error {
    constructor(statusCode, message) {
        super(message);
        this.name = "NetworkError";
        this.statusCode = statusCode;
    }
}

try {
    throw new ValidationError("email", "Invalid email");
} catch (e) {
    if (e instanceof ValidationError) {
        console.log(`Field: ${e.field}`);
    }
}

Async error handling

Errors in async functions must be caught with try/catch (for await) or .catch() (for Promises).

// async/await — use try/catch
async function fetchUser(id) {
    try {
        const res = await fetch(`/api/users/${id}`);
        if (!res.ok) throw new NetworkError(res.status, "Failed");
        return await res.json();
    } catch (error) {
        console.error("Fetch failed:", error);
        throw error;
    }
}

// Promise chain — use .catch()
fetch("/api/data")
    .then(res => res.json())
    .catch(err => console.error(err));

// Unhandled rejections
process.on("unhandledRejection", (reason) => {
    console.error("Unhandled:", reason);
});
Note: Unhandled Promise rejections are a common source of silent failures. Always handle errors in async code.

Exam tip

When writing custom errors, always set this.name in the constructor — otherwise instanceof checks work but error.name will show "Error" instead of your custom class name.

🎯

Think you're ready? Prove it.

Take the free JavaScript readiness test. Get a score, topic breakdown, and your exact weak areas.

Take the free JavaScript test →

Free · No sign-up · Instant results

← Previous
JavaScript Prototypes & Classes — Inheritance, extends & super
← All JavaScript guides