Skip to content

fix: retry version-index fetches and treat timeouts as transient - #20

Merged
chicoxyzzy merged 1 commit into
mainfrom
fix-transient-timeout-retry
Sep 9, 2026
Merged

chicoxyzzy merged 1 commit into
mainfrom
fix-transient-timeout-retry

Conversation

@chicoxyzzy

Copy link
Copy Markdown
Member

A macos-14 / 2024.5.0-mach smoke job failed with The operation was aborted due to timeout roughly 8s into the action, before any mirror was contacted. Two independent gaps caused it.

1. Version-index fetches had no retry

fetchJsonWithTimeout hits ziglang.org/download/index.json (and pkg.machengine.org/zig/index.json for mach versions) with an 8s timeout and no retry. This runs before mirror selection, so one slow response fails the whole job with nothing else attempted — no mirror racing, no fallback. Now wrapped in withRetry, matching how tarball and signature downloads are already handled.

2. isTransient did not classify timeouts

AbortSignal.timeout() rejects with a DOMException named TimeoutError, not AbortError, and its message matches none of the errno patterns:

name:    TimeoutError
message: The operation was aborted due to timeout

So isTransient returned false. This is the more consequential half: it means the mirror retry path was also silently declining to retry timeouts — a slow mirror was treated as a deterministic failure (like a signature mismatch) and written off after one attempt.

Tests

Added a case that derives the error from a real AbortSignal.timeout() rather than a hand-built stub, so it stays honest if the runtime's error shape changes.

73/73 pass; typecheck clean; dist/ rebuilt.

Version resolution fetches ziglang.org/download/index.json (and
pkg.machengine.org/zig/index.json for mach versions) before any mirror
is contacted, with an 8s timeout and no retry — so a single slow
response failed the whole job before anything else was attempted. This
took out a macos-14 mach smoke job when pkg.machengine.org was slow.

Two fixes:

- Wrap the index fetches in withRetry, matching how mirror downloads
  are already handled.
- Classify TimeoutError as transient. AbortSignal.timeout() rejects
  with a DOMException named TimeoutError, not AbortError, and its
  message ("The operation was aborted due to timeout") matches none of
  the errno patterns — so isTransient returned false and a slow mirror
  was written off as a deterministic failure, skipping its retry.
@chicoxyzzy
chicoxyzzy merged commit 7d1bd82 into main Sep 9, 2026
34 checks passed
@chicoxyzzy
chicoxyzzy deleted the fix-transient-timeout-retry branch September 9, 2026 17:14
chicoxyzzy pushed a commit that referenced this pull request Sep 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.0.4](v1.0.3...v1.0.4)
(2026-09-09)


### Fixed

* retry version-index fetches and treat timeouts as transient
([#20](#20))
([7d1bd82](7d1bd82))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: xyzzylabs-release-bot[bot] <298273869+xyzzylabs-release-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant