Glossary / Exception propagation

Exception propagation

Exception propagation is the movement of a thrown value through nested execution until a matching handler catches it or the runtime reports it as uncaught. Synchronous try/catch handles exceptions thrown during its dynamic execution. Promises and async/await create asynchronous propagation paths; callbacks scheduled for later run outside the original call stack.

Synchronous and asynchronous boundaries

try {
  setTimeout(() => { throw new Error("later"); }, 0);
} catch (error) {
  // Does not catch the timer callback's later throw.
}

async function load() {
  try {
    return await fetchData();
  } catch (error) {
    // Handles rejection from fetchData at the await point.
    throw new Error("Loading failed", { cause: error });
  }
}

A thrown error in a Promise executor rejects that Promise. A rejection propagates through .then chains until handled. await rethrows a rejected Promise’s reason at the await expression, where surrounding try/catch can handle it. Errors thrown inside later timer or event callbacks do not jump back into a completed caller’s try block.

finally is for cleanup and runs during normal or abrupt completion, but a return or throw from finally can override the earlier result/error. Catch only when you can recover, translate, add meaningful context, or safely report. Always observe asynchronous tasks; detached rejected Promises can become unhandled rejections.

Interview questions

  1. Can try/catch around setTimeout catch its callback error? No; the callback runs later on a separate task.
  2. How does await expose a rejection? It throws at the await expression.
  3. Can finally replace a prior error? Yes, a return/throw from finally can override completion.
  4. What is an unhandled rejection? A rejected Promise that reaches the host without a rejection handler.

References