π¨ JavaScript Β· Topic 15 of 20
Error Handling β JavaScript Questions with Answers
30 practice questions on Error Handling, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.
2 easy Β· 16 medium Β· 12 hard Β· Part of JavaScript: The language of the web - basics to advanced, 20 topics.
Medium questions (16)
Q2. medium
What is in the err object inside catch?
try { null.x; }
catch (err) {
console.log(err.name); // TypeError
console.log(err.message); // Cannot read properties of null
}
- A Properties like name, message and stack describing what went wrong
- B Only a string
- C The failed function
- D Nothing
Answer: A β Properties like name, message and stack describing what went wrong
err.name is the type (TypeError, ReferenceError...), err.message is the description, and err.stack shows where it happened.
Error object
Q3. medium
When does the finally block run?
try { await save(); }
catch (e) { showError(e); }
finally { hideSpinner(); } // always
- A ALWAYS - whether an error occurred, was caught, or the function returned
- B Only on success
- C Only on error
- D Only if catch is omitted
Answer: A β ALWAYS - whether an error occurred, was caught, or the function returned
finally is for cleanup that must happen regardless: hiding a loading spinner, closing a connection, releasing a lock.
finallyCleanup
Q5. medium
Why throw new Error("x") rather than throw "x"?
- A Error objects carry a stack trace and a name; a thrown string has neither
- B Strings are not allowed
- C It is only a style preference
- D Strings are faster
Answer: A β Error objects carry a stack trace and a name; a thrown string has neither
You can technically throw anything, but catch blocks then cannot rely on err.message or err.stack, making debugging much harder.
Error objectBest practices
Q6. medium
Which error occurs when you use a variable that was never declared?
- A ReferenceError
- B TypeError
- C SyntaxError
- D RangeError
Answer: A β ReferenceError
ReferenceError: x is not defined - usually a typo or a missing import. Contrast with TypeError, which means the value exists but is the wrong type.
ReferenceError
Q7. medium
Which error does null.name produce?
- A TypeError: Cannot read properties of null
- B ReferenceError
- C SyntaxError
- D No error
Answer: A β TypeError: Cannot read properties of null
The single most common runtime error in JavaScript. Guard with optional chaining (obj?.name) or a null check before accessing properties.
TypeErrorOptional chaining
Q8. medium
Can try/catch catch a SYNTAX error in the same file?
- A No - syntax errors are found before the code runs, so nothing executes
- B Yes, always
- C Only in strict mode
- D Only with finally
Answer: A β No - syntax errors are found before the code runs, so nothing executes
Parsing happens first; a malformed file never runs at all. try/catch only handles RUNTIME errors. (Syntax errors inside eval or dynamically loaded code are a special case.)
SyntaxErrorParse time
Q10. medium
How do you create a CUSTOM error type?
class ValidationError extends Error {
constructor(msg) { super(msg); this.name = "ValidationError"; }
}
try { throw new ValidationError("bad email"); }
catch (e) { if (e instanceof ValidationError) showFieldError(e.message); }
- A class ValidationError extends Error { }
- B function ValidationError() { }
- C new CustomError()
- D You cannot
Answer: A β class ValidationError extends Error { }
Extending Error lets callers catch your specific type with instanceof, which is far cleaner than string-matching messages.
Custom errorsextends
Q14. medium
What happens to an uncaught error in the browser?
- A It stops the current script and logs a red message in the console
- B The page closes
- C It is silently ignored
- D The browser crashes
Answer: A β It stops the current script and logs a red message in the console
Execution of that task halts, but the page stays open and later events still work. You can log such errors globally with window.addEventListener('error', ...).
Uncaught errorsDebugging
Q16. medium
What does the optional catch binding allow (ES2019)?
try { data = JSON.parse(text); }
catch { data = {}; } // no (e) needed
- A Omitting the parameter: catch { } when you do not need the error object
- B Catching two errors
- C Catching without try
- D Nothing
Answer: A β Omitting the parameter: catch { } when you do not need the error object
Useful when you only care that something failed, e.g. attempting an optional parse. Still, logging the error is usually wiser.
ES2019catch
Q18. medium
Which error type means a number is outside an allowed range?
- A RangeError - e.g. new Array(-1) or infinite recursion
- B TypeError
- C ReferenceError
- D SyntaxError
Answer: A β RangeError - e.g. new Array(-1) or infinite recursion
RangeError covers invalid lengths, bad toFixed digits, and 'Maximum call stack size exceeded' from runaway recursion.
RangeError
Q19. medium
How do you validate input and report a clear failure?
function setAge(age) {
if (!Number.isFinite(age) || age < 0)
throw new RangeError("age must be a positive number");
return age;
}
- A Check the condition and throw a descriptive Error the caller can catch
- B Return -1 silently
- C console.log a warning only
- D Ignore invalid input
Answer: A β Check the condition and throw a descriptive Error the caller can catch
Throwing forces the problem to be addressed and carries a message. Silent sentinel values like -1 are easy to forget to check and propagate bad data.
Validationthrow
Q22. medium
Where should you put try/catch for best results?
- A Around the smallest risky section, at a level where you can actually DO something about the error
- B Around the entire program
- C Around every single line
- D Never use it
Answer: A β Around the smallest risky section, at a level where you can actually DO something about the error
Catching too broadly hides which operation failed; catching where you cannot recover just adds noise. Let errors bubble to a layer that can show a message or retry.
Best practicesError boundaries
Q24. medium
How do you re-throw an error after logging it?
- A catch (e) { log(e); throw e; }
- B catch (e) { return e; }
- C catch (e) { throw; }
- D You cannot re-throw
Answer: A β catch (e) { log(e); throw e; }
Re-throwing lets a lower layer record the problem while a higher layer decides how to respond. (Unlike Python, a bare throw is invalid - you must name the error.)
Re-throwingLogging
Q26. medium
How do you catch errors from EVERY unhandled place in a browser app?
- A window.addEventListener('error', ...) and 'unhandledrejection'
- B One giant try/catch
- C It is impossible
- D console.log everything
Answer: A β window.addEventListener('error', ...) and 'unhandledrejection'
These global hooks are how error-reporting tools (Sentry and similar) capture crashes in production. They are a safety net, not a replacement for local handling.
Global handlersMonitoring
Q28. medium
Why check response.ok after fetch?
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
- A fetch only rejects on NETWORK failure - a 404 or 500 still resolves successfully
- B It is unnecessary
- C To parse JSON
- D To set headers
Answer: A β fetch only rejects on NETWORK failure - a 404 or 500 still resolves successfully
A very common bug: developers assume .catch() covers HTTP errors. You must inspect response.ok (or status) and throw yourself.
fetchHTTP errors
Q29. medium
What is a graceful fallback in error handling?
- A Showing a helpful message or default data instead of a blank/broken screen
- B Crashing quickly
- C Retrying forever
- D Hiding all errors from developers
Answer: A β Showing a helpful message or default data instead of a blank/broken screen
Users should never see a dead page. Show cached content, a retry button, or a clear message - while still logging the real error for developers.
UXResilience
Hard questions (12)
Q9. hard
What is the output?
try { console.log("A"); throw new Error("x"); console.log("B"); }
catch (e) { console.log("C"); }
console.log("D");
- A A C D - the throw skips the rest of try
- B A B C D
- C A C
- D C D
Answer: A β A C D - the throw skips the rest of try
Statements after the throw inside try never run. After catch handles the error, normal execution resumes.
Control flow
Q11. hard
How do you handle DIFFERENT error types differently?
catch (e) {
if (e instanceof ValidationError) showMsg(e);
else throw e; // let it bubble up
}
- A Check inside catch with instanceof and re-throw what you cannot handle
- B Write multiple catch blocks
- C catch (TypeError e) { }
- D JavaScript cannot distinguish them
Answer: A β Check inside catch with instanceof and re-throw what you cannot handle
JavaScript has only ONE catch block per try (unlike Java), so branch inside it. Re-throwing unknown errors avoids silently swallowing real bugs.
instanceofRe-throwing
Q12. hard
Does try/catch catch errors inside an ASYNC callback?
try { setTimeout(() => { throw new Error("x"); }, 0); } catch (e) { }
setTimeout(() => {
try { risky(); } catch (e) { handle(e); }
}, 0);
- A No - the callback runs later, long after the try block finished
- B Yes, always
- C Only with finally
- D Only in strict mode
Answer: A β No - the callback runs later, long after the try block finished
try/catch is synchronous: it only guards code running right now. The timer callback executes on a later tick with an empty stack, so the error becomes an uncaught exception. Put try/catch INSIDE the callback.
AsyncEvent loop
Q13. hard
How do you catch errors from a PROMISE?
fetch(url).then(r => r.json()).catch(err => show(err));
try { const r = await fetch(url); }
catch (err) { show(err); }
- A With .catch() on the chain, or try/catch around await
- B With a plain try/catch around the promise creation
- C Promises never fail
- D With if statements
Answer: A β With .catch() on the chain, or try/catch around await
Rejections are not thrown synchronously. Use promise.then().catch(), or await inside try/catch which converts rejection into a normal throw.
Promisesasync/await
Q15. hard
Why is an EMPTY catch block bad?
try { risky(); } catch (e) { }
- A It silently swallows errors, hiding bugs and making failures invisible
- B It is a syntax error
- C It is slower
- D It is fine
Answer: A β It silently swallows errors, hiding bugs and making failures invisible
Failures disappear with no trace, so the app misbehaves for reasons nobody can diagnose. At minimum log the error; ideally handle it or re-throw.
Anti-patternsBest practices
Q17. hard
What is the output?
function f() {
try { return "try"; }
finally { console.log("finally"); }
}
console.log(f());
- A finally then try - finally runs before the function actually returns
- B try then finally
- C only try
- D only finally
Answer: A β finally then try - finally runs before the function actually returns
The return value is computed, then finally executes, then the value is returned. Beware: a return inside finally would OVERRIDE the original return.
finallyreturn
Q20. hard
What does the error's stack property give you?
- A The chain of function calls that led to the error, with file and line numbers
- B The memory stack size
- C A list of variables
- D Nothing useful
Answer: A β The chain of function calls that led to the error, with file and line numbers
Read a stack from the top: the first line is where it threw, the lines below show who called it. Essential for locating the real source of a bug.
Stack traceDebugging
Q21. hard
What is an unhandled promise rejection?
- A A rejected promise with no .catch() - it logs a warning and can crash Node processes
- B A promise that never resolves
- C A syntax error
- D A resolved promise
Answer: A β A rejected promise with no .catch() - it logs a warning and can crash Node processes
Always terminate promise chains with .catch(), or wrap awaits in try/catch. Global safety net: window.addEventListener('unhandledrejection', ...).
PromisesAsync errors
Q23. hard
What is the output?
try { JSON.parse("{bad}"); }
catch (e) { console.log(e.name); }
- A SyntaxError - JSON.parse throws it at RUNTIME, so it IS catchable
- B TypeError
- C Nothing is logged
- D The code does not compile
Answer: A β SyntaxError - JSON.parse throws it at RUNTIME, so it IS catchable
This is a runtime SyntaxError produced by the parser function, unlike a syntax error in your own source. Always wrap JSON.parse of untrusted data in try/catch.
JSON.parseSyntaxError
Q25. hard
What does the cause option do (ES2022)?
throw new Error("Save failed", { cause: err })
- A Attaches the original error, preserving the chain for debugging
- B Sets the error message
- C Prevents the throw
- D Logs to the server
Answer: A β Attaches the original error, preserving the chain for debugging
Wrapping a low-level error in a friendlier one used to lose the original. cause keeps both, so err.cause reveals the underlying failure.
Error causeES2022
Q27. hard
What is the output?
async function f() { throw new Error("x"); }
f().catch(e => console.log("caught", e.message));
- A caught x - a throw inside async becomes a REJECTED promise
- B An uncaught error
- C Nothing
- D SyntaxError
Answer: A β caught x - a throw inside async becomes a REJECTED promise
async functions always return a promise; throwing rejects it. That is why await + try/catch works so naturally with them.
asyncPromises
Q30. hard
What is the output?
function f() {
try { throw new Error("a"); }
catch (e) { return "caught"; }
finally { return "finally"; }
}
console.log(f());
- A "finally" - a return in finally OVERRIDES the catch's return
- B "caught"
- C "a"
- D undefined
Answer: A β "finally" - a return in finally OVERRIDES the catch's return
finally has the last word, discarding pending returns AND pending errors. This is why returning from finally is discouraged - it can silently swallow exceptions.
finallyGotchas