- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript Error Handling Patterns
JavaScript Errors
JavaScript Error Handling Patterns
Good error handling is about deciding where a failure should be dealt with.
Wrapping everything in try catch is not error handling.
The useful question is who can actually do something about it.
Example
Example
javascript
function parseUser(text) {
try {
return JSON.parse(text);
} catch (error) {
return null;
}
}
console.log(parseUser("not json"));
console.log(parseUser('{"name":"Ada"}').name);The caller gets null rather than a crash.
Where to Handle
Catch where you can genuinely recover.
Let it travel up when the caller knows better than you do.
Handle it at the boundary: a button click, a request, a page load.
Syntax
Syntax
javascript
if (!valid) return fallback;A guard clause often removes the need to throw at all.
Fail Fast
Check input at the top of a function and stop immediately.
The error then points at the real cause, not three functions later.
Example
Example
javascript
function area(width, height) {
if (typeof width !== "number" || typeof height !== "number") {
throw new Error("width and height must be numbers");
}
return width * height;
}
let message;
try {
area("4", 5);
} catch (error) {
message = error.message;
}
console.log(message);Without the check this would silently return 20.
Guard Clauses
Often a simple check is better than throwing at all.
Example
Example
javascript
function greet(name) {
if (!name) {
return "Hello stranger";
}
return "Hello " + name;
}
console.log(greet(""));
console.log(greet("Ada"));Missing input is expected here, so it is not exceptional.
Do Not Catch What You Cannot Fix
Catching and ignoring turns a loud bug into a silent one.
If you cannot recover, let it travel up.
Example
Example
javascript
function risky() {
null.length;
}
function middle() {
return risky();
}
let name;
try {
middle();
} catch (error) {
name = error.name;
}
console.log(name);The middle function stayed out of the way, which is correct.
Adding Context When Rethrowing
If you rethrow, say something the original error did not.
Example
Example
javascript
function loadSettings(text) {
try {
return JSON.parse(text);
} catch (error) {
throw new Error("settings file is not valid JSON");
}
}
let message;
try {
loadSettings("nope");
} catch (error) {
message = error.message;
}
console.log(message);The new message says which file, which the original never knew.
Handling at the Boundary
One handler at the top is usually better than many scattered ones.
That is where you can show the user something useful.
Example
Example
javascript
function step(n) {
if (n === 2) throw new Error("step two failed");
return "step " + n;
}
function runAll() {
const done = [];
for (const n of [1, 2, 3]) {
done.push(step(n));
}
return done;
}
let message;
try {
runAll();
} catch (error) {
message = "stopped because " + error.message;
}
console.log(message);The loop did not need its own handler.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Error Handling Patterns</title>
</head>
<body>
<h1>Error Handling Patterns</h1>
<input id="text" value="not json">
<button id="load">Load</button>
<p id="out"></p>
<script>
function loadSettings(text) {
try {
return JSON.parse(text);
} catch (error) {
throw new Error("settings are not valid JSON");
}
}
document.getElementById("load").addEventListener("click", function () {
const out = document.getElementById("out");
try {
const settings = loadSettings(document.getElementById("text").value);
out.textContent = "Loaded " + Object.keys(settings).length + " settings";
} catch (error) {
out.textContent = "Could not load: " + error.message;
}
});
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try valid JSON:
Enter {"theme":"dark"} and click Load.
Important Points
- Catch only where you can recover.
- Check input at the top and fail fast.
- A guard clause is often better than throwing.
- Never catch and ignore.
- Handle errors at the boundary of your program.
Conclusion
Error handling is a design decision, not a wrapper you add everywhere.
The question is always who can do something useful about the failure.
A single handler at the boundary usually beats many scattered ones.
