Skip to content

feat(http/unstable): add isRetriableFetchError - #7298

Open
tomas-zijdemans wants to merge 2 commits into
denoland:mainfrom
tomas-zijdemans:feat-http-is-retriable-fetch-error
Open

feat(http/unstable): add isRetriableFetchError#7298
tomas-zijdemans wants to merge 2 commits into
denoland:mainfrom
tomas-zijdemans:feat-http-is-retriable-fetch-error

Conversation

@tomas-zijdemans

@tomas-zijdemans tomas-zijdemans commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Adds isRetriableFetchError, the missing predicate for retry()'s isRetriable hook. It recognizes transient fetch failures without substring-matching arbitrary error messages.

Implements the predicate half of #7296. The parser half is #7299.

Retriable cases

The predicate checks the thrown value and up to 8 objects in its cause chain, cycle-safe:

  • a Response, or an Error with an integer status from 100 through 599, when the status is 408, 429, or 5xx
  • an Error whose code is a known transient network code: ConnectionRefused or Timeout (Bun), or the errno-style ECONNREFUSED, ECONNRESET, ETIMEDOUT, ENOTFOUND, EAI_AGAIN (Bun and Node.js, including the cause of undici's fetch failed)
  • a TimeoutError DOMException from APIs such as AbortSignal.timeout()
  • a TypeError with an exact known failed-fetch message: fetch failed on Node.js and Deno 2.9+, one of the three browser strings, or the error sending request prefix from older Deno releases

AbortError stays false. Abort is caller intent, so retrying it is a bug.

Design notes

  1. This uses 500 <= status < 600 instead of isServerErrorStatus. That helper rejects unregistered codes such as Cloudflare's 520-526. A 522 test guards this.
  2. Modern Deno throws fetch failed, not error sending request ..., since fix(ext/fetch): reject transport failures with Node's "fetch failed" shape deno#35618. The older prefix stays because pre-2.9 Deno remains in the CI matrix.
  3. Bun does not throw fetch failed yet (alignment is in flight in fetch: reject network errors as TypeError('fetch failed' / 'terminated') with the system error as cause oven-sh/bun#35988 and fetch: reject network errors as TypeError('fetch failed') with cause, errno codes, and a caller stack oven-sh/bun#35998). Bun 1.4 throws TypeErrors identified by code, with messages that cannot be exact-matched: the DNS failure embeds the hostname. Hence the code allowlist, verified against real Bun 1.4 fetch failures. Deterministic codes such as ERR_INVALID_URL stay excluded, and a test guards non-string codes.

Review notes

  • Message matching is case-sensitive. That excludes deterministic Deno policy failures such as Fetch failed: Requests to port 6000 are blocked.
  • A cross-runtime test closes an ephemeral local port, fetches it, and checks the real transport error. The test also runs under Node and Bun, the first http/ test registered there.
  • Errors that store a Response on .response, including ky/got-style errors, are outside this API.
  • The remaining test-bun failure (isGlob works with the input that includes large number of open brackets) is unrelated: a Bun 1.4.0 regression in node:worker_threads Worker construction that also reproduces on main.

Testing

deno task ok and deno task test:node pass, and deno task test:bun (Bun 1.4.0) passes this module's tests. The new module has 19 tests with 100% line and branch coverage.

@github-actions github-actions Bot added the http label Aug 23, 2026
@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.04%. Comparing base (ca58f94) to head (f5a3aa7).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7298   +/-   ##
=======================================
  Coverage   95.03%   95.04%           
=======================================
  Files         617      618    +1     
  Lines       51637    51698   +61     
  Branches     9359     9381   +22     
=======================================
+ Hits        49075    49136   +61     
  Misses       2021     2021           
  Partials      541      541           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant