πŸŽ“ Velnov

🟨 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.

Key concepts in this topic

try/catchError objectfinallyCleanupthrowErrorBest practicesReferenceErrorTypeErrorOptional chainingSyntaxErrorParse timeControl flowCustom errorsextendsinstanceofRe-throwingAsyncEvent loopPromisesasync/awaitUncaught errorsDebuggingAnti-patterns

Jump to: Easy Β· Medium Β· Hard

Easy questions (2)

Q1. easy

Which structure catches runtime errors?

  1. A try { risky(); } catch (err) { handle(err); }
  2. B attempt { } rescue { }
  3. C try: ... except: ...
  4. D if (error) { }

Answer: A β€” try { risky(); } catch (err) { handle(err); }

Code that might throw goes in try; if an error occurs, execution jumps to catch with the error object. (except is Python, rescue is Ruby.)

try/catch

Q4. easy

How do you deliberately raise an error?

if (amount < 0) throw new Error("Amount cannot be negative");
  1. A throw new Error("message")
  2. B raise Error("message")
  3. C error("message")
  4. D return Error("message")

Answer: A β€” throw new Error("message")

throw stops execution and looks for the nearest catch. Always throw an Error OBJECT (not a string) so you get a stack trace.

throwError

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
}
  1. A Properties like name, message and stack describing what went wrong
  2. B Only a string
  3. C The failed function
  4. 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
  1. A ALWAYS - whether an error occurred, was caught, or the function returned
  2. B Only on success
  3. C Only on error
  4. 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"?

  1. A Error objects carry a stack trace and a name; a thrown string has neither
  2. B Strings are not allowed
  3. C It is only a style preference
  4. 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?

  1. A ReferenceError
  2. B TypeError
  3. C SyntaxError
  4. 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?

  1. A TypeError: Cannot read properties of null
  2. B ReferenceError
  3. C SyntaxError
  4. 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?

  1. A No - syntax errors are found before the code runs, so nothing executes
  2. B Yes, always
  3. C Only in strict mode
  4. 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); }
  1. A class ValidationError extends Error { }
  2. B function ValidationError() { }
  3. C new CustomError()
  4. 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?

  1. A It stops the current script and logs a red message in the console
  2. B The page closes
  3. C It is silently ignored
  4. 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
  1. A Omitting the parameter: catch { } when you do not need the error object
  2. B Catching two errors
  3. C Catching without try
  4. 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?

  1. A RangeError - e.g. new Array(-1) or infinite recursion
  2. B TypeError
  3. C ReferenceError
  4. 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;
}
  1. A Check the condition and throw a descriptive Error the caller can catch
  2. B Return -1 silently
  3. C console.log a warning only
  4. 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?

  1. A Around the smallest risky section, at a level where you can actually DO something about the error
  2. B Around the entire program
  3. C Around every single line
  4. 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?

  1. A catch (e) { log(e); throw e; }
  2. B catch (e) { return e; }
  3. C catch (e) { throw; }
  4. 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?

  1. A window.addEventListener('error', ...) and 'unhandledrejection'
  2. B One giant try/catch
  3. C It is impossible
  4. 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}`);
  1. A fetch only rejects on NETWORK failure - a 404 or 500 still resolves successfully
  2. B It is unnecessary
  3. C To parse JSON
  4. 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?

  1. A Showing a helpful message or default data instead of a blank/broken screen
  2. B Crashing quickly
  3. C Retrying forever
  4. 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");

  1. A A C D - the throw skips the rest of try
  2. B A B C D
  3. C A C
  4. 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
}
  1. A Check inside catch with instanceof and re-throw what you cannot handle
  2. B Write multiple catch blocks
  3. C catch (TypeError e) { }
  4. 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);
  1. A No - the callback runs later, long after the try block finished
  2. B Yes, always
  3. C Only with finally
  4. 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); }
  1. A With .catch() on the chain, or try/catch around await
  2. B With a plain try/catch around the promise creation
  3. C Promises never fail
  4. 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) { }

  1. A It silently swallows errors, hiding bugs and making failures invisible
  2. B It is a syntax error
  3. C It is slower
  4. 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());

  1. A finally then try - finally runs before the function actually returns
  2. B try then finally
  3. C only try
  4. 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?

  1. A The chain of function calls that led to the error, with file and line numbers
  2. B The memory stack size
  3. C A list of variables
  4. 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?

  1. A A rejected promise with no .catch() - it logs a warning and can crash Node processes
  2. B A promise that never resolves
  3. C A syntax error
  4. 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); }

  1. A SyntaxError - JSON.parse throws it at RUNTIME, so it IS catchable
  2. B TypeError
  3. C Nothing is logged
  4. 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 })

  1. A Attaches the original error, preserving the chain for debugging
  2. B Sets the error message
  3. C Prevents the throw
  4. 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));

  1. A caught x - a throw inside async becomes a REJECTED promise
  2. B An uncaught error
  3. C Nothing
  4. 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());

  1. A "finally" - a return in finally OVERRIDES the catch's return
  2. B "caught"
  3. C "a"
  4. 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

Practice β€œError Handling” as a quiz