fix(installer): retry backend install on transient PyPI failures#1561
Conversation
The AppImage backend bootstrap runs a single `uv pip install` with no retry.
The gaia wheel is installed from a local file in the release pipeline, but its
heavy transitive deps (scipy, numpy, torch) are still fetched live from PyPI —
so one mid-download network hiccup ("stream closed because of a broken pipe")
fails the entire install. In release v0.20.1 this killed the AppImage distro
matrix smoke test and blocked the whole publish.
Wrap the install stage in a bounded retry (3 attempts, linear backoff) that
fires only on transient network signatures and still fails loudly afterward.
Dependency-resolution errors and Windows file-lock (os error 32) are not
retried — they need user action, not another attempt. This also hardens real
end-user installs on flaky networks, where the install stage does the heaviest
network work.
SummarySolid, tightly-scoped resilience fix — Approve. It wraps the single I verified Issues Found🟢 Minor — retry detection is one-sided on the combined output (backend-installer.cjs:1204-1208) 🟢 Minor — timeout regex prefix groups are decorative (backend-installer.cjs:41) Strengths
VerdictApprove. No blocking issues. The two notes are optional polish. Before merge, it's worth getting the jest suite green in CI (the author flagged it couldn't run locally) and re-running the AppImage distro matrix to confirm the original failure is resolved end-to-end — both already listed as unchecked items in the test plan. |
Why this matters
Release v0.20.1 failed to publish: the AppImage distro matrix → Row 1 (Ubuntu) smoke test never reached
state: readybecause the backend bootstrap'suv pip installdied mid-download fetchingscipyfrom PyPI —error sending request ... stream closed because of a broken pipe. The installer runs a single install attempt with no retry, so one transient PyPI hiccup failed the whole install and blocked the entire release.Before: any momentary PyPI/network blip during install fails the AppImage smoke test → release pipeline blocked (and real end-users on flaky networks get a hard install failure). After: the install stage retries transient network failures (3 attempts, linear backoff) and only then fails — loudly, with the same actionable error as before. Deterministic failures (dependency-resolution conflicts, Windows file-lock
os error 32) are deliberately not retried.The local-wheel mechanism (
GAIA_LOCAL_WHEEL) only removes the gaia package from the PyPI dependency — the heavy transitive deps (scipy, numpy, torch) are still fetched live, which is the part that flaked.Test plan
node -c backend-installer.cjs— syntax cleanisTransientNetworkErrorvalidated against the exact v0.20.1 broken-pipe output plus common transient phrasings; confirms it does not matchNo solution found(resolution) oros error 32(file lock)cd tests/electron && npm test backend-installer-lock.test.cjs(jest unavailable in my sandbox — needs a runner with deps installed)