JavaScript Error Handling Interview Questions (try, catch, finally)
In the Error Handling article, we learned how try, catch and finally work. In interviews, the questions are usually about the order things run in, and the cases where try...catch doesn’t do what you’d expect.
Let’s go through them. For every question, try to work out the answer yourself before reading the explanation.
1. In what order do try, catch and finally run?
Section titled “1. In what order do try, catch and finally run?”try {
console.log("A");
throw new Error("Oops");
console.log("B");
} catch (err) {
console.log("C", err.message);
} finally {
console.log("D");
}
console.log("E");
Answer: A, C Oops, D, E
In the above example, you can see that:
Ais printed, then thethrowhappens.- As soon as an error is thrown, JavaScript skips the rest of the
tryblock. That’s whyBnever prints. - Control jumps to
catch, which printsCwith the error message. finallyalways runs, soDis printed.- Since the error was handled, the program keeps going and prints
E.
2. Does finally run after return in JavaScript?
Section titled “2. Does finally run after return in JavaScript?”function test() {
try {
return "from try";
} finally {
console.log("finally runs");
}
}
console.log(test());
Answer: finally runs, then from try
Hmm, you may be wondering how finally can run if try already returned.
In the above example, you can see that:
- When
tryhitsreturn, JavaScript remembers the return value, but doesn’t leave the function yet. - It runs the
finallyblock first, which printsfinally runs. - Only then does the function actually return
"from try", andconsole.logprints it.
So finally really does always run, even after a return.
3. What happens when both try and finally have a return?
Section titled “3. What happens when both try and finally have a return?”function test() {
try {
return "from try";
} finally {
return "from finally";
}
}
console.log(test());
Answer: from finally
In the above example, you can see that:
trywants to return"from try", butfinallystill has to run first.finallyhas its ownreturn, which overrides the one fromtry.- So the function returns
"from finally".
4. Why doesn’t try...catch catch errors inside setTimeout?
Section titled “4. Why doesn’t try...catch catch errors inside setTimeout?”try {
setTimeout(() => {
throw new Error("Late error");
}, 1000);
} catch (err) {
console.log("Caught:", err.message);
}
Answer: Nothing is caught. After a second, you get Uncaught Error: Late error.
Wait, what? The throw is clearly inside the try!
In the above example, you can see that:
setTimeoutdoesn’t run the callback right away. It just schedules it for later.- So the
tryblock finishes almost instantly, and no error has happened yet.catchhas nothing to catch. - One second later, the callback runs and throws. But by then, the
try...catchis long gone.
try...catch only catches errors that happen while it’s running. The fix is to put the try...catch inside the callback:
setTimeout(() => {
try {
throw new Error("Late error");
} catch (err) {
console.log("Caught:", err.message); // Caught: Late error
}
}, 1000);
5. How do nested try...catch blocks work?
Section titled “5. How do nested try...catch blocks work?”try {
try {
throw new Error("Inner");
} catch (err) {
console.log("Inner catch:", err.message);
throw new Error("Outer");
} finally {
console.log("Inner finally");
}
} catch (err) {
console.log("Outer catch:", err.message);
}
Answer:
Inner catch: Inner
Inner finally
Outer catch: Outer
In the above example, you can see that:
- The inner
trythrows"Inner", so the innercatchhandles it. - The inner
catchthen throws a new error,"Outer". - Before that error leaves the inner block, the inner
finallyruns. - The new error then travels up to the outer
try, where the outercatchhandles it.
6. What are the common error types in JavaScript?
Section titled “6. What are the common error types in JavaScript?”console.log(userName); // ReferenceError: userName is not defined
null.length; // TypeError: Cannot read properties of null
new Array(-1); // RangeError: Invalid array length
JSON.parse("{bad json}"); // SyntaxError: Expected property name or '}' in JSON
In the above example, you can see that:
- ReferenceError: You used a variable that doesn’t exist.
- TypeError: You did something a value doesn’t support, like reading a property of
nullor calling something that isn’t a function. - RangeError: A number is outside the allowed range, like a negative array length or a stack overflow.
- SyntaxError: The code (or JSON, in this case) isn’t written correctly.
7. Can try...catch catch a syntax error?
Section titled “7. Can try...catch catch a syntax error?”try {
let a = ;
} catch (err) {
console.log("Caught it!");
}
Answer: No. The whole script fails with SyntaxError: Unexpected token ';', and nothing runs at all.
In the above example, you can see that:
- Before running any code, JavaScript first reads the whole script to check that it’s written correctly.
let a = ;is broken, so JavaScript refuses to run anything. Thetryblock never even starts.try...catchcan only catch errors that happen while the code is running.
But wait, didn’t we catch a SyntaxError from JSON.parse in the last question? Yes! That’s because the JavaScript code there was fine. The JSON text was broken, and JSON.parse threw the error while it was running.
8. How do you catch only a specific type of error in JavaScript?
Section titled “8. How do you catch only a specific type of error in JavaScript?”function parseUser(json) {
try {
const user = JSON.parse(json);
return user.name.toUpperCase();
} catch (err) {
if (err instanceof SyntaxError) {
console.log("Invalid JSON, please check the data.");
} else {
throw err;
}
}
}
parseUser("{bad json}"); // Invalid JSON, please check the data.
parseUser("{}"); // Uncaught TypeError: Cannot read properties of undefined
In the above example, you can see that:
instanceofchecks what type of error we got.- If it’s a
SyntaxError, we know the JSON was bad, so we handle it with a friendly message. - Anything else, like the
TypeErrorfrom a missingname, is a bug we didn’t expect. So we rethrow it withthrow err.
Interviewers ask this because catching every error and ignoring it hides real bugs. Only handle the errors you expect, and let the rest through.
9. Why should you throw an Error object instead of a string?
Section titled “9. Why should you throw an Error object instead of a string?”try {
throw "Something went wrong";
} catch (err) {
console.log(err.message); // undefined
console.log(err.stack); // undefined
}
try {
throw new Error("Something went wrong");
} catch (err) {
console.log(err.message); // Something went wrong
console.log(err.stack); // Error: Something went wrong at ...
}
In the above example, you can see that:
- JavaScript lets you throw anything, even a plain string.
- But a string doesn’t have
messageorstack. Any code that expects them getsundefined. - An
Errorobject gives you the message, plus a stack trace that shows exactly where the error came from.
That stack trace is what saves you hours of debugging, so always throw new Error(...).
🧵 Wrapping It Up
Section titled “🧵 Wrapping It Up”You practiced how to:
- Predict the order in which
try,catchandfinallyrun - Know what happens when
returnis used insidetryandfinally - Explain why
try...catchcan’t catch errors in asetTimeoutcallback or a syntax error in your code - Name the common error types, handle only the ones you expect, and rethrow the rest
Just remember this one rule. try...catch only catches errors that happen while it’s running, and finally always gets the last word.