Chapter 18 Advanced 50 Questions

Practice Questions — Error Handling and Debugging

← Back to Notes
9 Easy
9 Medium
6 Hard

Topic-Specific Questions

Question 1
Easy
What is the output?
try {
  console.log("A");
  console.log("B");
} catch (error) {
  console.log("C");
}
console.log("D");
No error occurs in the try block.
A
B
D
Question 2
Easy
What is the output?
try {
  console.log("A");
  JSON.parse("invalid");
  console.log("B");
} catch (error) {
  console.log("C");
}
console.log("D");
JSON.parse with invalid input throws SyntaxError.
A
C
D
Question 3
Easy
What is the output?
try {
  console.log("start");
} catch (error) {
  console.log("error");
} finally {
  console.log("done");
}
finally always runs, even when there is no error.
start
done
Question 4
Easy
What type of error does this code throw?
console.log(myVar);
myVar has not been declared anywhere.
ReferenceError: myVar is not defined
Question 5
Easy
What type of error does this code throw?
const num = 42;
num.toUpperCase();
toUpperCase is a string method, not a number method.
TypeError: num.toUpperCase is not a function
Question 6
Medium
What is the output?
try {
  throw new Error("oops");
  console.log("after throw");
} catch (error) {
  console.log(error.message);
}
console.log("end");
throw immediately exits the try block.
oops
end
Question 7
Medium
What is the output?
function test() {
  try {
    return 1;
  } finally {
    console.log("finally");
  }
}

const result = test();
console.log(result);
finally runs even after a return statement.
finally
1
Question 8
Medium
What is the output?
try {
  const obj = null;
  console.log(obj.name);
} catch (error) {
  console.log(error.name);
  console.log(error.message.includes("null"));
}
Accessing a property of null throws TypeError.
TypeError
true
Question 9
Medium
What is the output?
try {
  JSON.parse("invalid");
} catch (error) {
  console.log(error instanceof SyntaxError);
  console.log(error instanceof Error);
  console.log(error instanceof TypeError);
}
SyntaxError is a subclass of Error.
true
true
false
Question 10
Hard
What is the output?
function outer() {
  try {
    inner();
    console.log("after inner");
  } catch (error) {
    console.log("outer caught:", error.message);
  }
}

function inner() {
  throw new Error("inner error");
}

outer();
console.log("done");
The error from inner() propagates up to outer's try-catch.
outer caught: inner error
done
Question 11
Hard
What is the output?
function test(val) {
  try {
    if (val < 0) throw new RangeError("negative");
    if (typeof val !== "number") throw new TypeError("not a number");
    return val * 2;
  } catch (error) {
    return error.name + ": " + error.message;
  } finally {
    console.log("finally for " + val);
  }
}

console.log(test(5));
console.log(test(-3));
console.log(test("abc"));
finally runs before the return value is delivered each time.
finally for 5
10
finally for -3
RangeError: negative
finally for abc
TypeError: not a number
Question 12
Hard
What is the output?
try {
  try {
    throw new TypeError("inner");
  } catch (e) {
    console.log("inner catch:", e.message);
    throw new RangeError("re-thrown");
  } finally {
    console.log("inner finally");
  }
} catch (e) {
  console.log("outer catch:", e.name, e.message);
} finally {
  console.log("outer finally");
}
The inner catch throws a NEW error. The inner finally still runs. The new error propagates to outer catch.
inner catch: inner
inner finally
outer catch: RangeError re-thrown
outer finally
Question 13
Easy
What type of error does this code throw?
const arr = new Array(-1);
Array length cannot be negative.
RangeError: Invalid array length
Question 14
Medium
What is the output?
function greet(name) {
  if (typeof name !== "string") {
    throw new TypeError("Name must be a string");
  }
  return "Hello, " + name;
}

try {
  console.log(greet("Aarav"));
  console.log(greet(42));
} catch (error) {
  console.log(error.message);
}
console.log("done");
First call succeeds. Second call throws.
Hello, Aarav
Name must be a string
done
Question 15
Easy
What is the output?
console.warn("low disk space");
console.log("program continues");
console.warn does not stop execution.
low disk space (as a warning)
program continues

Mixed & Application Questions

Question 1
Easy
What is the output?
try {
  const x = 10;
  console.log(x / 2);
} catch (error) {
  console.log("Error!");
}
10 / 2 is a valid operation.
5
Question 2
Easy
What is the output?
console.assert(5 > 3, "This should not log");
console.assert(2 > 7, "Math is broken");
console.assert only logs when the condition is FALSE.
Assertion failed: Math is broken
Question 3
Medium
What is the output?
function safeDivide(a, b) {
  if (b === 0) {
    throw new Error("Cannot divide by zero");
  }
  return a / b;
}

const results = [];
const pairs = [[10, 2], [6, 0], [9, 3]];

for (const [a, b] of pairs) {
  try {
    results.push(safeDivide(a, b));
  } catch (error) {
    results.push(error.message);
  }
}
console.log(results);
Each pair is processed independently. Errors are caught per iteration.
[5, "Cannot divide by zero", 3]
Question 4
Medium
What is the output?
function parseAge(input) {
  const age = Number(input);
  if (isNaN(age)) throw new TypeError("Not a number: " + input);
  if (age < 0) throw new RangeError("Negative age: " + age);
  return age;
}

const inputs = ["25", "abc", "-5", "16"];
for (const input of inputs) {
  try {
    console.log(parseAge(input));
  } catch (e) {
    console.log(e.name);
  }
}
Number('abc') is NaN. Number('-5') is -5.
25
TypeError
RangeError
16
Question 5
Medium
What is the output?
let count = 0;

try {
  count++;
  JSON.parse("bad");
  count++;
} catch (e) {
  count += 10;
} finally {
  count += 100;
}

console.log(count);
Track count: starts at 0, incremented in try, error occurs, then catch and finally both run.
111
Question 6
Hard
What is the output?
function validate(data) {
  if (!data) throw new Error("No data");
  if (!data.name) throw new Error("No name");
  if (typeof data.age !== "number") throw new TypeError("Bad age");
  return "Valid";
}

const tests = [null, {}, { name: "A" }, { name: "B", age: 16 }];

for (const test of tests) {
  try {
    console.log(validate(test));
  } catch (e) {
    console.log(e.message);
  }
}
Each test object fails at a different validation check (or passes).
No data
No name
Bad age
Valid
Question 7
Hard
What is the output?
function f() {
  try {
    return "try";
  } catch (e) {
    return "catch";
  } finally {
    return "finally";
  }
}
console.log(f());
If finally has a return, it overrides all previous returns.
finally
Question 8
Medium
Why should you always throw Error objects (like new Error('msg')) instead of strings (like throw 'msg')?
What properties do Error objects have that strings do not?
Error objects provide .name (error type), .message (description), and .stack (where it happened). Strings have none of these. Without a stack trace, you cannot tell where the error originated. Without .name, you cannot distinguish error types. Throwing strings makes debugging much harder.
Question 9
Hard
Why does try-catch NOT work around setTimeout or event listeners for catching errors inside them?
Think about when the callback actually executes.
try-catch only catches errors that happen synchronously within the try block. setTimeout and event listener callbacks run LATER, after the try-catch has already completed. By the time the callback executes and throws, the try-catch is no longer active. You need to put try-catch inside the callback, or use async/await.

Multiple Choice Questions

MCQ 1
Which error occurs when you use a variable that has not been declared?
  • A. TypeError
  • B. SyntaxError
  • C. ReferenceError
  • D. RangeError
Answer: C
C is correct. Using an undeclared variable throws ReferenceError: x is not defined. TypeError is for wrong type operations, SyntaxError is for bad code structure.
MCQ 2
What block always runs, whether an error occurred or not?
  • A. try
  • B. catch
  • C. throw
  • D. finally
Answer: D
D is correct. finally always runs: after try succeeds, after catch handles an error, and even after return statements.
MCQ 3
What does error.message contain?
  • A. The line number of the error
  • B. The name of the error type
  • C. A human-readable description of what went wrong
  • D. The full stack trace
Answer: C
C is correct. error.message is a human-readable string describing the error. error.name is the type. error.stack is the trace.
MCQ 4
Which error does null.toString() throw?
  • A. ReferenceError
  • B. TypeError
  • C. SyntaxError
  • D. RangeError
Answer: B
B is correct. Calling a method on null (or accessing a property) throws TypeError: Cannot read properties of null.
MCQ 5
What does console.assert(false, 'test') do?
  • A. Logs 'test' because the condition is false
  • B. Throws an error
  • C. Logs nothing
  • D. Crashes the program
Answer: A
A is correct. console.assert logs the message only when the condition is false. It does not throw errors or crash -- it just logs to the console.
MCQ 6
What is the correct way to create a custom error?
  • A. throw 'my error message';
  • B. throw new Error('my error message');
  • C. console.error('my error message');
  • D. return new Error('my error message');
Answer: B
B is correct. throw new Error('...') creates an Error object and throws it. Option A throws a string (bad practice). Option C just logs. Option D creates but does not throw.
MCQ 7
What console method displays data as a formatted table?
  • A. console.display()
  • B. console.format()
  • C. console.table()
  • D. console.grid()
Answer: C
C is correct. console.table() displays arrays and objects as a formatted table in the browser console. Very useful for debugging data.
MCQ 8
If a try block has a return statement and a finally block also has a return statement, which return wins?
  • A. The try return
  • B. The finally return
  • C. Both returns execute
  • D. It throws an error
Answer: B
B is correct. The finally return overrides the try return. This is because finally always runs last. However, returning from finally is considered bad practice.
MCQ 9
How do you check if an error is a specific type?
  • A. error.type === 'TypeError'
  • B. error instanceof TypeError
  • C. typeof error === 'TypeError'
  • D. error.is(TypeError)
Answer: B
B is correct. instanceof checks if an object is an instance of a class. error instanceof TypeError is true for TypeErrors (and false for other types).
MCQ 10
What keyboard shortcut opens browser DevTools?
  • A. Ctrl+D
  • B. Ctrl+Shift+I or F12
  • C. Alt+F4
  • D. Ctrl+Alt+J
Answer: B
B is correct. F12 or Ctrl+Shift+I opens DevTools in Chrome, Firefox, and Edge. This is the most important tool for debugging web applications.
MCQ 11
Why does try { setTimeout(() => { throw new Error(); }, 0); } catch(e) {} NOT catch the error?
  • A. setTimeout does not support errors
  • B. The catch block only runs once
  • C. The callback runs later, after the try-catch has finished
  • D. Arrow functions cannot throw errors
Answer: C
C is correct. try-catch is synchronous. The setTimeout callback runs asynchronously in a later event loop tick. By then, the try-catch is long gone.
MCQ 12
What is a breakpoint in browser DevTools?
  • A. A line where the code crashes
  • B. A marker that pauses code execution at a specific line for inspection
  • C. A line that is skipped during execution
  • D. A point where the browser restarts
Answer: B
B is correct. A breakpoint pauses execution at that line, letting you inspect variable values, the call stack, and step through code line by line. Set them by clicking a line number in the Sources tab.
MCQ 13
What is the difference between console.warn() and throw new Error()?
  • A. They do the same thing
  • B. warn logs a message without stopping execution; throw stops execution and requires catch
  • C. throw is for minor issues, warn is for critical errors
  • D. warn only works in Node.js
Answer: B
B is correct. console.warn logs a yellow warning and execution continues normally. throw stops execution immediately and the error must be caught by a try-catch or it crashes the program.
MCQ 14
What does console.error('msg') do?
  • A. Throws an error and stops the program
  • B. Logs a red error message to the console without stopping execution
  • C. Crashes the browser
  • D. Sends the error to the server
Answer: B
B is correct. console.error logs a message styled as an error (red in most browsers) but does NOT throw an error or stop execution.
MCQ 15
What does the error.stack property contain?
  • A. The error message
  • B. The line number only
  • C. A full trace of function calls leading to the error
  • D. The file name only
Answer: C
C is correct. error.stack contains a string showing the chain of function calls (call stack) that led to the error, including file names and line numbers. This is the most useful property for debugging.
MCQ 16
Which error occurs when you call JSON.parse('invalid')?
  • A. TypeError
  • B. ReferenceError
  • C. SyntaxError
  • D. RangeError
Answer: C
C is correct. Invalid JSON causes a SyntaxError because the input string does not follow JSON syntax rules.
MCQ 17
What is Step Over (F10) in browser DevTools?
  • A. Skips the entire function
  • B. Executes the current line and moves to the next line
  • C. Goes inside a function call
  • D. Resumes normal execution
Answer: B
B is correct. Step Over executes the current line completely (including any function calls) and pauses at the next line. Step Into (F11) would go inside function calls.
MCQ 18
Can you catch a SyntaxError with try-catch if it is in the same code block?
  • A. Yes, always
  • B. No, SyntaxErrors are detected before the code runs, so try-catch never executes
  • C. Only in strict mode
  • D. Only in async functions
Answer: B
B is correct. SyntaxErrors in your code are caught during parsing, before any code runs. The try-catch itself would not execute. However, SyntaxErrors from eval() or JSON.parse() CAN be caught because they happen at runtime.
MCQ 19
What property gives the error type name (like 'TypeError' or 'RangeError')?
  • A. error.type
  • B. error.name
  • C. error.kind
  • D. error.class
Answer: B
B is correct. error.name contains the error type as a string, like 'TypeError', 'RangeError', or 'SyntaxError'.

Coding Challenges

Challenge 1: Safe JSON Parser

Easy
Write a function safeJsonParse(str, fallback) that parses a JSON string and returns the result. If parsing fails, return the fallback value instead of crashing.
Sample Input
safeJsonParse('{"name":"Aarav"}', {}), safeJsonParse('bad', [])
Sample Output
{ name: 'Aarav' } []
Use try-catch. Return the fallback on any error.
function safeJsonParse(str, fallback) {
  try {
    return JSON.parse(str);
  } catch (error) {
    return fallback;
  }
}

console.log(safeJsonParse('{"name":"Aarav"}', {}));
console.log(safeJsonParse('bad', []));
console.log(safeJsonParse(null, { error: true }));

Challenge 2: Error Type Identifier

Easy
Write a function identifyError(fn) that takes a function, calls it, and returns the error type name if it throws, or 'No error' if it succeeds.
Sample Input
() => null.x, () => unknownVar, () => 42
Sample Output
TypeError ReferenceError No error
Use try-catch and error.name.
function identifyError(fn) {
  try {
    fn();
    return "No error";
  } catch (error) {
    return error.name;
  }
}

console.log(identifyError(() => null.x));        // TypeError
console.log(identifyError(() => JSON.parse('{')));  // SyntaxError
console.log(identifyError(() => 42));             // No error

Challenge 3: Input Validator with Custom Errors

Medium
Create a ValidationError class that extends Error and has a 'field' property. Write a validateStudent(data) function that validates name (string, 2+ chars), age (number, 5-25), and email (must include @). Throw ValidationError with the field name for each failure.
Sample Input
{ name: 'A', age: 16, email: 'a@b.com' }
Sample Output
ValidationError on field 'name': Name must be at least 2 characters
Custom error class with field property. Use instanceof to check error type.
class ValidationError extends Error {
  constructor(field, message) {
    super(message);
    this.name = 'ValidationError';
    this.field = field;
  }
}

function validateStudent(data) {
  if (typeof data.name !== 'string' || data.name.length < 2) {
    throw new ValidationError('name', 'Name must be at least 2 characters');
  }
  if (typeof data.age !== 'number' || data.age < 5 || data.age > 25) {
    throw new ValidationError('age', 'Age must be a number between 5 and 25');
  }
  if (!data.email || !data.email.includes('@')) {
    throw new ValidationError('email', 'Email must contain @');
  }
  return true;
}

const tests = [
  { name: 'A', age: 16, email: 'a@b.com' },
  { name: 'Aarav', age: 3, email: 'a@b.com' },
  { name: 'Priya', age: 15, email: 'bad' },
  { name: 'Rohan', age: 16, email: 'r@x.com' }
];

for (const test of tests) {
  try {
    validateStudent(test);
    console.log(test.name + ': Valid');
  } catch (e) {
    if (e instanceof ValidationError) {
      console.log(test.name + ': ' + e.field + ' - ' + e.message);
    }
  }
}

Challenge 4: Retry Function

Medium
Write a function retry(fn, maxAttempts) that calls fn() up to maxAttempts times. If fn succeeds, return the result. If fn throws and there are attempts left, try again. If all attempts fail, throw the last error.
Sample Input
A function that fails randomly
Sample Output
Attempt 1: failed Attempt 2: success -> 42
Track attempts. Re-throw the last error after all attempts fail.
function retry(fn, maxAttempts) {
  let lastError;
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      const result = fn();
      console.log('Attempt ' + attempt + ': success -> ' + result);
      return result;
    } catch (error) {
      lastError = error;
      console.log('Attempt ' + attempt + ': failed - ' + error.message);
    }
  }
  throw lastError;
}

let callCount = 0;
function unreliable() {
  callCount++;
  if (callCount < 3) throw new Error('not ready');
  return 42;
}

try {
  retry(unreliable, 5);
} catch (e) {
  console.log('All attempts failed');
}

Challenge 5: Safe Property Accessor

Medium
Write a function safeAccess(obj, path) where path is a dot-separated string like 'a.b.c'. Return the value at that path, or undefined if any part is missing. Do NOT use optional chaining -- use try-catch instead.
Sample Input
({ a: { b: { c: 42 } } }, 'a.b.c')
Sample Output
42
Use try-catch and a loop. Do not use optional chaining (?.).
function safeAccess(obj, path) {
  try {
    const keys = path.split('.');
    let current = obj;
    for (const key of keys) {
      current = current[key];
    }
    return current;
  } catch (error) {
    return undefined;
  }
}

const data = { a: { b: { c: 42 } } };
console.log(safeAccess(data, 'a.b.c'));   // 42
console.log(safeAccess(data, 'a.b'));     // { c: 42 }
console.log(safeAccess(data, 'a.x.y'));   // undefined
console.log(safeAccess(data, 'z'));        // undefined

Challenge 6: Error Statistics Collector

Hard
Write a function testAll(functions) that takes an array of functions, calls each one, and returns an object with: { successes: count, errors: { TypeError: count, RangeError: count, ... } }.
Sample Input
[() => 42, () => null.x, () => JSON.parse('{')]
Sample Output
{ successes: 1, errors: { TypeError: 1, SyntaxError: 1 } }
Use try-catch and error.name to categorize.
function testAll(functions) {
  const result = { successes: 0, errors: {} };

  for (const fn of functions) {
    try {
      fn();
      result.successes++;
    } catch (error) {
      const type = error.name;
      result.errors[type] = (result.errors[type] || 0) + 1;
    }
  }

  return result;
}

const fns = [
  () => 42,
  () => null.x,
  () => JSON.parse('{'),
  () => [].length,
  () => undefined.name,
  () => new Array(-1)
];

console.log(testAll(fns));
// { successes: 2, errors: { TypeError: 2, SyntaxError: 1, RangeError: 1 } }

Challenge 7: Build a Debug Logger

Hard
Create a DebugLogger class with methods: log(msg), warn(msg), error(msg), time(label), timeEnd(label), getLog(). It should store all messages internally with timestamps. getLog() returns all stored messages as an array.
Sample Input
logger.log('hello'); logger.warn('warning'); logger.getLog()
Sample Output
[{type:'log', msg:'hello', time:...}, {type:'warn', msg:'warning', time:...}]
Store messages in an array. Include type, message, and timestamp for each.
class DebugLogger {
  constructor() {
    this.messages = [];
    this.timers = {};
  }

  log(msg) {
    this.messages.push({ type: 'log', msg, time: Date.now() });
    console.log(msg);
  }

  warn(msg) {
    this.messages.push({ type: 'warn', msg, time: Date.now() });
    console.warn(msg);
  }

  error(msg) {
    this.messages.push({ type: 'error', msg, time: Date.now() });
    console.error(msg);
  }

  time(label) {
    this.timers[label] = Date.now();
  }

  timeEnd(label) {
    if (this.timers[label]) {
      const duration = Date.now() - this.timers[label];
      this.log(label + ': ' + duration + 'ms');
      delete this.timers[label];
    }
  }

  getLog() {
    return this.messages;
  }
}

const logger = new DebugLogger();
logger.log('App started');
logger.warn('Deprecated function used');
logger.time('process');
for (let i = 0; i < 100000; i++) {}
logger.timeEnd('process');
console.log(logger.getLog());

Need to Review the Concepts?

Go back to the detailed notes for this chapter.

Read Chapter Notes

Want to learn web development with a live mentor?

Explore our Frontend Masterclass