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

  1. Retry the build — mid-body resets are usually transient
  2. Increase the HTTP client timeout for release downloads
  3. Check proxy/firewall stability for large-ish text downloads from the release host
  4. 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

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


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)