Relationships
#1131 swamp update silently reports 'up to date' forever if the stable pointer loses its redirect-location metadata
Opened by swamp_lord · 7/14/2026
Summary
A latent single point of failure in the self-update path, found while fixing #1130. It is not currently firing — but if it ever does, it fails silently, on every client, indefinitely. No error, no warning, no non-zero exit.
The failure
HttpUpdateChecker.checkForUpdate (src/infrastructure/update/http_update_checker.ts) HEADs the stable pointer and looks for a redirect in three headers: location, x-amz-website-redirect-location, x-amz-meta-x-amz-website-redirect-location. If none is present but the response is 200, it returns the stable URL itself.
UpdateService.check() (src/domain/update/update_service.ts) then calls parseVersionFromRedirectUrl(), which matches /\/swamp\/([^/]+)\/binary\//. The stable URL has no version segment — it is /swamp/stable/binary/... — so the match yields "stable" (or null). Either way it lands here:
const latestVersion = parseVersionFromRedirectUrl(redirectUrl);
if (!latestVersion || latestVersion === this.currentVersion) {
return { status: "up_to_date", ... };
}A stable pointer that serves correct bytes but carries no redirect metadata therefore makes every client on every platform report up to date, forever.
Why it's reachable
The version pointer is an artifact of the S3-era publisher: the stable object carries x-amz-meta-x-amz-website-redirect-location pointing at the versioned URL, and it survives only because the publisher preserves that header when writing the object. DigitalOcean Spaces has no static-website hosting or redirect metadata of its own.
giga-swamp's to-dos/03-ci-binary-publish-retarget.md contemplates changing exactly that publisher, and notes the stable pointer becomes "a literal copy of the latest tarball". A future publisher that writes the copy without that metadata breaks updates silently across the entire installed base — and nothing would catch it, because the artifact still downloads and checksums fine.
It is also worse than a normal update failure: there is no error to swallow, so the autoupdate log records nothing and swamp doctor install shows nothing either.
Expected behavior
check() should distinguish "no update available" from "I could not determine the latest version". Options:
- If
checkForUpdatefound no redirect and is returning the stable URL itself, treat that as an error rather than a version. - If
parseVersionFromRedirectUrl()returnsnullor a non-CalVer segment (e.g."stable"), raise aUserErrorinstead of silently reporting current. - Add a release-pipeline assertion that the published stable pointer resolves to a versioned URL, so this cannot ship broken.
Notes
- Found while fixing #1130; not caused by it. The #1130 edge fix depends on the same header, but incidentally.
- No test currently covers the "200 with no redirect header" branch of
checkForUpdate.
In Progress
Click a lifecycle step above to view its details.
Sign in to post a ripple.