ipfs/kubo · error
download returned HTTP
Error message
download returned HTTP %d
What it means
downloadAsset fetches a GitHub release asset via its browser_download_url (GitHub CDN, no auth) and requires an exact HTTP 200. Any other status code (404, 403, 429, 5xx) makes it abort with this error before reading the body.
Solutions
- Wait a few hours and retry if the release is brand new (artifacts may still be uploading)
- Check the asset exists at the URL in a browser (404 means the asset name/tag changed)
- Retry later on 429/5xx — GitHub CDN rate limits are temporary
- Check for a proxy/firewall intercepting HTTPS to github.com and use a direct connection
- Verify the release tag passed to the update command is a real, published release
Defensive patterns
Strategy: retry
Validate before calling
// before calling the updater, check reachability of the asset URL
resp, err := http.Head(assetURL)
if err != nil {
return fmt.Errorf("cannot reach github.com: %w", err)
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("asset unavailable, HTTP %d — retry later", resp.StatusCode)
} Try / catch
// CLI errors surface as the command's error output, not panics
if err := cmd.Run(); err != nil {
if strings.Contains(err.Error(), "download returned HTTP") {
// transient GitHub CDN issue: wait and retry with backoff
time.Sleep(retryDelay)
return cmd.Run()
}
return err
} Prevention
- Do not run `ipfs update` in the minutes right after a release is announced; wait for artifacts to propagate
- Check the release page in a browser to confirm the asset for your OS/arch exists first
- Avoid unauthenticated high-frequency API/CDN access from shared CI IPs to dodge 429 rate limits
- Ensure no transparent proxy intercepts HTTPS traffic to github.com
When it happens
Trigger: The GET of a release asset URL returns a non-200 status: the asset was removed or renamed, the release tag is wrong, GitHub rate-limits or blocks the CDN request, a proxy intercepts the download, or the binary upload for a fresh release is not yet visible on the CDN.
Common situations: Running `ipfs update` right after a release is announced while CI artifacts are still propagating to GitHub's CDN; an interrupted/deleted release; corporate proxies returning 403/502 challenge pages; unauthenticated rate limiting (429) on shared CI IPs.
Related errors
- downloading checksum file
- GitHub API returned HTTP
- download exceeds maximum size of
- GitHub API rate limit exceeded
- reading download
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/93ada949bd195cbc.
Report an issue: GitHub.
Appendix: source
Thrown at core/commands/update_github.go:225
}
// downloadAsset downloads a release asset by its browser_download_url.
// This hits GitHub's CDN directly, not the API, so no auth headers are needed.
func downloadAsset(ctx context.Context, url string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.Header.Set("User-Agent", "kubo/"+version.CurrentVersionNumber)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("downloading asset: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("download returned HTTP %d", resp.StatusCode)
}
data, err := io.ReadAll(io.LimitReader(resp.Body, maxDownloadSize+1))
if err != nil {
return nil, fmt.Errorf("reading download: %w", err)
}
if int64(len(data)) > maxDownloadSize {
return nil, fmt.Errorf("download exceeds maximum size of %d bytes", maxDownloadSize)
}
return data, nil
}
// downloadAndVerifySHA512 downloads the .sha512 sidecar file for the given
// archive URL and verifies the archive data against it.
func downloadAndVerifySHA512(ctx context.Context, data []byte, archiveURL string) error {
sha512URL := archiveURL + ".sha512"
checksumData, err := downloadAsset(ctx, sha512URL)
if err != nil {View on GitHub (pinned to 329838acdf)