Error Handling with try/catch
Catching runtime errors gracefully instead of letting them crash your program.
2 min read
Things fail at runtime — a variable doesn't exist, JSON is malformed, a network call errors out. try/catch lets JavaScript recover from that instead of stopping execution entirely.
The basic pattern
try {
const data = JSON.parse("{ invalid json");
console.log(data);
} catch (error) {
console.log("Failed to parse:", error.message);
}JavaScript runs the try block; if anything inside it throws, execution jumps immediately to catch, skipping the rest of the try block entirely.
The error object
try {
null.someProperty;
} catch (error) {
console.log(error.name); // "TypeError"
console.log(error.message); // "Cannot read properties of null..."
}Every built-in error is an instance of Error (or a subclass like TypeError, RangeError, or SyntaxError), carrying a name and a message you can inspect or log.
Throwing your own errors
function withdraw(balance, amount) {
if (amount > balance) {
throw new Error("Insufficient funds");
}
return balance - amount;
}
try {
withdraw(100, 150);
} catch (error) {
console.log(error.message); // "Insufficient funds"
}throw works with any value technically, but always throw an Error object (or a subclass) rather than a plain string — Error objects carry a stack trace, which is invaluable for debugging where the error actually originated.
finally
try {
riskyOperation();
} catch (error) {
console.error(error);
} finally {
console.log("This always runs, error or not.");
}finally runs unconditionally — whether the try block succeeded, threw, or even returned early — making it the right place for cleanup that must happen regardless of the outcome, like closing a connection or hiding a loading indicator.
try/catch and async code
As covered earlier in this course, try/catch also catches a rejected promise when the await for it is inside the try block — the same mechanism handles both synchronous throws and asynchronous rejections:
async function loadData() {
try {
const response = await fetch("/api/data");
return await response.json();
} catch (error) {
console.error("Load failed:", error);
return null;
}
}What not to catch
Catch errors you can meaningfully recover from or report — a failed network request, invalid user input. Catching everything indiscriminately (an empty catch block, or one that just swallows the error silently) hides real bugs instead of surfacing them, the same trap covered for Python's bare except: in other courses on this site — the principle is identical here.
The final lesson in this course covers JSON directly — the data format that JSON.parse and JSON.stringify convert to and from, and the one nearly every API you'll fetch from actually speaks.