Error Handling & Debugging

Medium100% Free~20 mins#errors#try-catch#finally#debugging#call-stack#exceptions#v8
Key Learning Objectives
✓

Master try/catch/finally control flow and understand how finally return statements override prior returns.

✓

Understand error propagation through the call stack and how unhandled exceptions trigger uncaught error events.

✓

Distinguish built-in error constructors (Error, TypeError, RangeError, SyntaxError, ReferenceError) and custom error subclasses.

✓

Recognize the critical difference between synchronous thrown exceptions and asynchronous rejected promises.

The Interview Problem

What is logged to the console when the following code executes, and why does returning inside a finally block override previous return statements?

1function processData(val) {
2 try {
3 if (val < 0) {
4 throw new RangeError('Must be positive');
5 }
6 return val * 2;
7 } catch (err) {
8 if (err instanceof RangeError) {
9 return 'handled-range';
10 }
11 throw err;
12 }
13}
14
15function computeWithFinally() {
16 try {
17 throw new Error('fail');
18 } catch (err) {
19 return 'from-catch';
20 } finally {
21 return 'from-finally';
22 }
23}
24
25const res1 = processData(5);
26const res2 = processData(-1);
27const res3 = computeWithFinally();
28
29console.log(res1, res2, res3);
Predict Console Output
Interactive Challenge

Select the option that matches what standard ECMAScript prints to the console:

10 handled-range from-finally

10 handled-range from-catch

10 unhandled-error from-finally

10 handled-range fail

V8 Engine Execution Trace
Step 1 of 8 (Line 1)

Global Execution Context initializes function declarations in the global environment record.

Call Stack (Top = Active)
Global Execution Context
Lexical Scope / Bindings
processData:FunctionRef#processData
computeWithFinally:FunctionRef#computeWithFinally
Console Stream
> [empty]

Deep Technical Breakdown

The Mechanics of JavaScript Exception Handling

  1. Try-Catch-Finally Execution Order:
    • The try block executes until normal completion or an exception is thrown.
    • If an exception is thrown, synchronous execution in try suspends immediately and control transfers to catch (err).
    • The finally block always runs, whether an error occurred, was caught, or the function attempted to return early.
  2. The Finally Return Override Trap:
    • According to ECMAScript specification §14.15 (The try Statement), if a finally block exits with an abrupt completion (e.g. return value or throw error), that completion overwrites any prior completion from try or catch.
    • If catch threw an error and finally returned a value, the error is swallowed silently and the function returns normally. For this reason, ESLint flags no-unsafe-finally.
  3. Synchronous vs Asynchronous Errors:
    • try...catch can only catch synchronous errors in the current call stack turn.
    • If an asynchronous operation (e.g. setTimeout, un-awaited fetch) throws inside a callback, it runs in a different event loop tick; an outer try...catch will not catch it.
    • With async/await, await converts rejected promises into synchronous-style exceptions that try...catch can intercept.
Common Traps & Mistakes

Placing a return statement inside a `finally` block, which silently discards uncaught exceptions and creates subtle debugging nightmares.

Wrapping asynchronous callbacks with synchronous `try...catch`: `try { setTimeout(() => { throw new Error(); }, 10); } catch (e) {}` will NOT catch the error.

Catching errors without re-throwing unknown error types: catching everything with an empty `catch {}` masks syntax and reference errors.

FAANG Follow-Up Probes
Probe #1

Why does window.onerror or window.addEventListener('error') capture script errors while window.addEventListener('unhandledrejection') captures unhandled promises?

Probe #2

How does the V8 engine construct an Error stack trace using Error.captureStackTrace(), and how do you customize stack traces in Node.js?

Probe #3

How does React's componentDidCatch and getDerivedStateFromError (Error Boundaries) interact with JavaScript's try/catch model?