Learn how to use try, catch, and finally
to handle runtime errors gracefully — keeping your program running instead of crashing.
Exception Handling in JavaScript is a mechanism used to handle
runtime errors using constructs like try, catch, and
finally, ensuring the program continues to run without crashing.
Without exception handling, a single error stops all code from running. With it, you control exactly what happens when something goes wrong.
Exception handling means: "If something breaks, don't crash — handle it smartly."
try {
let result = 10 / 0;
console.log(result); // Infinity — not an error in JS
} catch (error) {
console.log("Something went wrong:", error.message);
}
try wraps code that might failcatch runs only if an error is thrown — here none is, so it's skippedInfinity, not an errortry {
console.log(userName); // userName is not defined
} catch (error) {
console.log("Error:", error.message);
}
ReferenceErrorerror.message gives the human-readable reason for the errortry...catch this would crash all code below ittry {
let num = 5;
console.log(num);
} catch (error) {
console.log("Error occurred");
} finally {
console.log("This always runs");
}
finally runs no matter what — error or no errorfunction checkAge(age) {
try {
if (age < 18) {
throw new Error("You are underage");
}
console.log("Access granted");
} catch (error) {
console.log("Blocked:", error.message);
}
}
checkAge(16);
checkAge(21);
throw lets you create your own errors with custom messagesnew Error("...") is preferred over throwing a plain stringcatch block immediatelyThink of an online payment process:
A real-world input validator — it uses throw to raise custom errors
and catch to display them to the user without crashing the page.
<!DOCTYPE html>
<html>
<head><title>Exception Handling</title></head>
<body style="font-family:sans-serif;padding:20px;background:#f8f9fa">
<h2>Enter a number</h2>
<input type="text" id="num" placeholder="e.g. 42">
<button onclick="checkNumber()">Check</button>
<p id="result" style="margin-top:10px;font-weight:600"></p>
<script>
function checkNumber() {
let value = document.getElementById("num").value;
let out = document.getElementById("result");
try {
if (value === "") throw new Error("Input cannot be empty");
let number = Number(value);
if (isNaN(number)) throw new Error("Not a valid number");
out.style.color = "green";
out.innerText = "Valid number: " + number;
} catch (error) {
out.style.color = "red";
out.innerText = "Error: " + error.message;
} finally {
console.log("Validation attempted");
}
}
</script>
</body>
</html>
function divide(a, b) {
// your code here
}
console.log(divide(10, 2));
console.log(divide(10, 0));
try...catch inside divide()b is 0, throw new Error("Cannot divide by zero")function checkEligibility(age) {
// your code here
}
checkEligibility(20);
checkEligibility(15);
age < 18"Eligible" if the age is validcatch to print the error messagefinally to always log "Check complete"catch block receives the error object and decides what to do with it — log it, show a message, or recover.
finally block do?
finally always executes — it's the right place for cleanup code like closing connections or hiding loading spinners.
throw used for?
throw lets you raise your own errors with custom messages — useful for enforcing business rules like age limits or required fields.
Always throw an Error object instead of a plain string — you get a stack trace and a .message property:
// Avoid
throw "Invalid input";
// Prefer
throw new Error("Invalid input");
try {
throw new Error("Invalid input");
} catch (e) {
console.log(e.message); // "Invalid input"
console.log(e instanceof Error); // true
}
Don't overuse try...catch — wrap only the risky operation, not your entire program. Catching everything hides bugs you need to know about.
Validate inputs before risky operations — use isNaN() for numbers and check for empty strings up front:
function parseAmount(input) {
if (input === "") throw new Error("Field is required");
if (isNaN(Number(input))) throw new Error("Must be a number");
return Number(input);
}
try {
console.log(parseAmount("42"));
console.log(parseAmount("abc"));
} catch (e) {
console.log("Caught:", e.message);
}
Keep error messages user-friendly in the UI — log the technical details to the console, show a simple message to the user:
try {
// risky operation
} catch (e) {
console.error("Debug:", e.message); // for developer
showToUser("Something went wrong. Try again."); // for user
}
What gets printed, and in what order? Predict before running.
try {
let x = y + 10; // y is not defined
} catch (e) {
console.log("Error handled");
} finally {
console.log("Done");
}
// Step 1: try block runs → y is not defined → ReferenceError thrown
// Step 2: catch block catches it → prints "Error handled"
// Step 3: finally always runs → prints "Done"
// Output (in order):
// "Error handled"
// "Done"
// Key insight: finally runs even after catch — it is truly unconditional.