JavaScript Notes
Master JavaScript try...catch...finally with error flow diagrams, async error handling, nested try-catch, real-world examples, common mistakes, and interview Q&A.
try...catch...finally is JavaScript's primary mechanism for handling runtime errors gracefully — preventing crashes and giving you a chance to recover, log, or show user-friendly messages when something goes wrong.
📊 Error Flow Diagram
💻 Example 1 — Basic Try...Catch
try {
const data = JSON.parse('{ "name": "Riya" }'); // valid JSON
console.log("Parsed:", data.name);
JSON.parse("{ bad json }"); // throws SyntaxError
console.log("This never runs");
} catch (error) {
console.log("Error caught!");
console.log("Type:", error.constructor.name);
console.log("Message:", error.message);
}
console.log("Program continues after catch");Parsed: Riya
Error caught!
Type: SyntaxError
Message: Unexpected token 'b', "{ bad json }" is not valid JSON
Program continues after catch💻 Example 2 — Try...Catch...Finally
function loadConfig(configString) {
console.log("⏳ Loading config...");
try {
const config = JSON.parse(configString);
console.log("✅ Config loaded:", config.theme);
return config;
} catch (error) {
console.log("❌ Failed to parse config:", error.message);
return { theme: "default" }; // fallback value
} finally {
// Always runs — whether parse succeeded or failed
console.log("🔚 Config loading complete");
}
}
console.log("--- Valid config ---");
loadConfig('{"theme": "dark", "language": "en"}');
console.log("\n--- Invalid config ---");
loadConfig("not valid json at all");--- Valid config --- ⏳ Loading config... ✅ Config loaded: dark 🔚 Config loading complete --- Invalid config --- ⏳ Loading config... ❌ Failed to parse config: Unexpected token 'o', "not valid json at all" is not valid JSON 🔚 Config loading complete
💻 Example 3 — Catching Different Error Types
HELLO WORLD 🔴 Type Error: Input cannot be null or undefined 🔴 Type Error: Expected string, got number 🟡 Range Error: Input cannot be empty
💻 Example 4 — Async/Await with Try...Catch
Fetching user 1... Fetching user 99... ✅ Found: Riya (riya@wohotech.in) Done fetching user 1 ❌ Error: User 99 not found Done fetching user 99
💻 Example 5 — Nested Try...Catch
function processOrder(order) {
try {
// Outer try handles general errors
if (!order) throw new Error("Order is required");
try {
// Inner try handles payment errors specifically
if (!order.paymentMethod) throw new Error("Payment method missing");
console.log(`💳 Processing payment via ${order.paymentMethod}`);
} catch (paymentError) {
console.log(`⚠️ Payment issue: ${paymentError.message} — using default`);
order.paymentMethod = "cash";
}
console.log(`📦 Order #${order.id} processed via ${order.paymentMethod}`);
} catch (error) {
console.log(`🚫 Fatal error: ${error.message}`);
}
}
processOrder({ id: 101, paymentMethod: "UPI" });
processOrder({ id: 102 }); // no payment method
processOrder(null); // null order💳 Processing payment via UPI 📦 Order #101 processed via UPI ⚠️ Payment issue: Payment method missing — using default 📦 Order #102 processed via cash 🚫 Fatal error: Order is required
📋 Error Types in JavaScript
| Error Type | When it occurs |
|---|---|
Error | Generic base error |
TypeError | Wrong type used — calling non-function, accessing null |
RangeError | Value outside allowed range — new Array(-1) |
ReferenceError | Variable not defined |
SyntaxError | Invalid code / invalid JSON — JSON.parse("{bad}") |
URIError | Invalid URI encoding |
EvalError | Error in eval() |
⚠️ Common Mistakes
❌ Mistake 1 — Silent Error Swallowing
try {
riskyOperation();
} catch (error) {
// Empty catch — error is hidden, impossible to debug!
}// GOOD — always at minimum log the error
try {
riskyOperation();
} catch (error) {
console.error("Operation failed:", error.message);
}❌ Mistake 2 — Wrapping Too Much Code in One Try Block
// BAD — can't tell which line caused the error
try {
const data = fetchData();
const parsed = parseData(data);
const result = transformData(parsed);
saveResult(result);
} catch (error) {
console.log(error.message); // Which step failed??
}❌ Mistake 3 — Async Errors Not Caught Without await/try-catch
// BAD — promise rejection is unhandled!
async function load() {
const data = fetchFromAPI(); // ← missing 'await'!
console.log(data.name); // TypeError: Cannot read properties of undefined
}
// GOOD
async function load() {
try {
const data = await fetchFromAPI();
console.log(data.name);
} catch (error) {
console.error("Load failed:", error.message);
}
}❌ Mistake 4 — Returning from finally Overrides catch Return
function test() {
try {
throw new Error("oops");
} catch (e) {
return "from catch";
} finally {
return "from finally"; // ← overrides catch's return!
}
}
console.log(test());from finally
🎯 Key Takeaways
trywraps risky code;catchhandles errors;finallyalways runs for cleanup- The
catchblock receives an Error object with.message,.name,.stack - Use
error instanceof TypeErrorto handle different error types differently async/awaiterrors must be insidetry...catch— useawaiton every async call- Never silently swallow errors — always log, recover, or rethrow
finallyis perfect for releasing resources: closing files, stopping loading spinners, clearing timeouts- Avoid returning from
finally— it can suppress errors and overridecatchreturns
❓ Interview Questions
Q1. What is try...catch...finally in JavaScript? > It's a control flow structure for error handling. Code in try runs first. If an error is thrown, execution jumps to catch where you handle it. finally runs after both — no matter whether an error occurred or not.
Q2. What properties does the error object have? > error.message (human-readable description), error.name (error class name like "TypeError"), error.stack (stack trace showing where the error occurred). Custom errors can add more properties.
Q3. Does finally always run? > Yes — finally runs even if try succeeds, if catch runs, or if a return is hit inside try or catch. The only exceptions are process.exit(), infinite loops, or power failure.
Q4. How do you handle errors in async/await functions? > Wrap await calls in try...catch. Without try...catch, unhandled promise rejections will cause warnings in Node.js and can crash the process in newer versions.
Q5. What is the difference between throw inside catch and a normal return? > Rethrowing (throw error) passes the error up to the next enclosing catch or crashes if none exists. A normal return from catch resumes normal execution in the outer scope.
Q6. Can you have multiple catch blocks? > No — JavaScript only allows one catch block per try. Distinguish error types inside the single catch using instanceof: if (error instanceof TypeError) { ... }.
Q7. What happens if an error is thrown inside catch? > It propagates to the next outer try...catch. The finally block still runs before propagation.
Q8. What is the difference between try...catch and .catch() on a Promise? > try...catch handles synchronous errors and async errors when used with await. .catch() handles Promise rejections in the .then() chain pattern. With async/await, try...catch is preferred for cleaner, more readable code.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript Try Catch Finally – Error Handling Complete Guide.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, error, handling, try
Related JavaScript Master Course Topics