JavaScript › Error Handling

Why can errors thrown inside a setTimeout callback NOT be caught by a surrounding try/catch?

Advanced

Answer

The try/catch block finishes executing (and its stack frame is gone) long before the setTimeout callback actually runs on a later turn of the event loop — by the time the error is thrown, there's no enclosing try/catch left to catch it.
try {
  setTimeout(() => { throw new Error('too late!'); }, 100);
} catch (err) {
  // never runs — the throw happens asynchronously, after this try/catch exits
}
Real-world example A confusing bug where a developer expects a try/catch to catch an error from an async callback, but it silently escapes to the console instead.

Common follow-ups: Where should the try/catch actually go to catch an error thrown inside a setTimeout callback?