Learning on Web Dev Open is free for all.

Systems Thinking > Failure, deliberatelyThe failures that never throw
Phase 03Failure, deliberately150 of 434

The failures that never throw

fetch resolves happily on a 500. An async callback handed to forEach loses its rejection entirely. Neither shows up in a try block.

Concept14 minAI adversary

fetch rejects only on a network-level failure. A 404, a 500, a redirect loop that ends somewhere strange: all of those resolve, and if you do not check response.ok you will call .json() on an error page and get a parse error that names the wrong problem. This is the most common silent failure in front-end code and it takes one line to prevent.

The second is a promise nobody awaited. An async callback passed to forEach, a fire-and-forget call with no catch, a promise stored and abandoned: the rejection has no handler, so it surfaces as an unhandledrejection event on window rather than as an exception, and no try/catch anywhere can catch it because the surrounding block finished long before.

The third is the optimistic default: ?? [], || {}, an optional chain that quietly resolves to undefined. Each of those turns a missing value into a plausible one, which is exactly what makes the eventual symptom so far from the cause. Add listeners for unhandledrejection and error at your entry point so the ones you missed are at least loud, then treat every one that fires as a design question rather than a log line.

You should now be able to

  • Name three failures that produce no exception
  • Install the last-resort handlers that make them visible
Ask the community

Loading…