Error handling
try/catch, throwing errors, and failing safely.
- Catch errors with try/catch/finally
- Throw Error objects for invalid situations
- Handle errors in async code
When something goes wrong at runtime, JavaScript throws an error. Unhandled,
it stops execution (you read these traces in the error-messages fundamentals
lesson). try/catch lets you respond instead of crashing.
try / catch / finally
try {
const data = JSON.parse(input); // throws if input isn't valid JSON
use(data);
} catch (err) {
console.error("bad input:", err.message);
} finally {
cleanup(); // runs either way — success or failure
}If the try block throws, control jumps to catch with the error; finally
always runs, which is the place for cleanup that must happen regardless.
Throw for invalid situations
When your code hits something invalid, throw an Error rather than returning a
nonsense value — fail loudly and early (the "say what you mean" principle):
function setAge(age) {
if (age < 0) {
throw new Error("age cannot be negative");
}
return age;
}Throw Error objects (not strings) — they carry a message and a stack trace,
which is what makes debugging possible.
Errors in async code
Because await throws a rejected promise, the same try/catch works for async
code — no special syntax:
try {
const user = await loadUser(1);
} catch (err) {
console.error("failed to load:", err.message);
}Catch errors you can actually handle; don't wrap everything in an empty catch
that hides bugs. An error you can't sensibly recover from is often best left to
propagate so it's visible.
Where to go next
Last in this module: fetch and APIs — talking to the network, pulling everything in this track together.