github/copilot-sdk · error
failed to read checksums
Error message
failed to read checksums: %w
What it means
Reading the SHA256SUMS.txt response body failed; the error is wrapped so the underlying I/O cause is preserved. getReleaseChecksum cannot parse checksums without the full body, so downloadCLIBinary aborts.
Solutions
- Retry the build — mid-body resets are usually transient
- Increase the HTTP client timeout for release downloads
- Check proxy/firewall stability for large-ish text downloads from the release host
- Verify the release host itself is healthy (curl the checksums URL repeatedly)
Example fix
// before
contents, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read checksums: %w", err)
}
// after
contents, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return "", fmt.Errorf("failed to read checksums: %w", err)
} Defensive patterns
Strategy: retry
Try / catch
contents, err := io.ReadAll(resp.Body)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// retry once before failing
}
return "", fmt.Errorf("failed to read checksums: %w", err)
} Prevention
- Set explicit timeouts on releaseHTTPClient and retry on timeout errors
- Avoid flaky proxies for release downloads
- Read with io.LimitReader to bound response size
- Check server health if resets recur on the same host
When it happens
Trigger: io.ReadAll(resp.Body) returns an error while draining the checksums response: connection reset mid-body, timeout during transfer, or server closing the connection early.
Common situations: Flaky network or proxy dropping long-running responses; server truncating the response; aggressive HTTP client timeout on slow links.
Related errors
- failed to download checksums
- failed to download
- failed to save tarball
- Failed to write a frame to the in-process runtime…
- Failed to download from
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/c16953489434bd07.
Report an issue: GitHub.
Appendix: source
Thrown at go/cmd/bundler/main.go:977
func getReleaseChecksum(version, assetName string) (string, error) {
baseURL := cliDownloadBaseURL()
cacheKey := baseURL + "\x00" + version
checksums, ok := releaseChecksumCache[cacheKey]
if !ok {
checksumsURL := fmt.Sprintf("%s/v%s/SHA256SUMS.txt", baseURL, version)
fmt.Printf("Downloading checksums from %s...\n", checksumsURL)
resp, err := releaseHTTPClient.Get(checksumsURL)
if err != nil {
return "", fmt.Errorf("failed to download checksums: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to download checksums: %s", resp.Status)
}
contents, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read checksums: %w", err)
}
checksums = parseReleaseChecksums(string(contents))
releaseChecksumCache[cacheKey] = checksums
}
checksum, ok := checksums[assetName]
if !ok {
return "", fmt.Errorf("SHA256SUMS.txt does not contain %s", assetName)
}
return checksum, nil
}
// downloadCLIBinary downloads the verified release package and extracts the CLI binary. It
// returns the extracted binary path and the downloaded tarball path (retained so
// callers can extract additional files, such as the runtime library).
func downloadCLIBinary(runtimePlatform, binaryName, cliVersion, destDir string) (string, string, error) {
assetName := releaseAssetName(cliVersion, runtimePlatform)
expectedChecksum, err := getReleaseChecksum(cliVersion, assetName)
if err != nil {View on GitHub (pinned to cd8cf15dc3)