Skip to main content

Error Handling


try / catch / finally

try {
// code that might throw
const result = JSON.parse("invalid json");
console.log(result);
} catch (error) {
console.error("Error:", error.message);
console.error("Name:", error.name); // "SyntaxError"
console.error("Stack:", error.stack);
} finally {
// ALWAYS runs, even if error or return
console.log("This always runs");
}

Built-in Error Types

// SyntaxError: invalid syntax
JSON.parse("bad json"); // SyntaxError

// ReferenceError: accessing undefined variable
console.log(undeclaredVar); // ReferenceError

// TypeError: wrong type operation
null.toString(); // TypeError
undefined.length; // TypeError

// RangeError: value out of valid range
new Array(-1); // RangeError
(1.234).toFixed(200); // RangeError

// URIError
decodeURIComponent("%"); // URIError

// AggregateError: Promise.any when all reject

Throwing Errors

// Throw any value
throw "Something went wrong";
throw 42;
throw { message: "Custom error" };

// Best practice: throw Error objects
throw new Error("Something went wrong");
throw new TypeError("Expected a string");
throw new RangeError("Value must be between 0 and 100");

Custom Error Classes

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

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

// Using custom errors
try {
const age = -5;
if (age < 0) throw new ValidationError("Age must be positive", "age");
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation failed on field: ${error.field}`);
} else if (error instanceof NetworkError) {
console.log(`Network error: ${error.statusCode}`);
} else {
throw error; // re-throw unknown errors!
}
}

Error Handling in Async Code

// With Promises
fetch("/api/data")
.then(res => res.json())
.catch(err => console.error("Fetch error:", err))
.finally(() => setLoading(false));

// With async/await
async function loadData() {
try {
const res = await fetch("/api/data");
if (!res.ok) throw new NetworkError(`HTTP ${res.status}`, res.status);
const data = await res.json();
return data;
} catch (error) {
if (error instanceof NetworkError) {
// handle network errors
} else {
throw error; // re-throw unexpected errors
}
}
}

Global Error Handling

// Browser: unhandled errors
window.addEventListener("error", (event) => {
console.error(event.error);
});

// Browser: unhandled Promise rejections
window.addEventListener("unhandledrejection", (event) => {
console.error("Unhandled Promise rejection:", event.reason);
event.preventDefault(); // suppress default console error
});

// Node.js
process.on("uncaughtException", (err) => {
console.error("Uncaught:", err);
process.exit(1);
});

process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled rejection:", reason);
});

MCQ — Error Handling

Q1: What does the finally block do?

A) Runs only if no error occurred B) Runs only if an error occurred C) Always runs, regardless of error or return ✅ D) Runs the error handling code

Answer: C

Q2: Which error type is thrown when calling a method on null?

A) ReferenceError B) SyntaxError C) TypeErrorD) NullError

Answer: C

Q3: What is best practice when catching errors?

A) Catch all errors with an empty catch block B) Handle specific error types and re-throw unknown errors ✅ C) Log all errors and continue D) Always suppress errors

Answer: B

Q4: How do you create a custom error class?

A) const e = { type: "CustomError", message: "..." } B) class CustomError extends Error { constructor(...) { super(...); } }C) function CustomError(msg) { this.message = msg; }

Answer: B

Q5: Which event catches unhandled Promise rejections in the browser?

A) error B) promiserejection C) unhandledrejectionD) catch

Answer: C