hashicorp/packer · error
failed reading response body for %s: %w
Error message
failed reading response body for %s: %w
What it means
After a 200 response for the SHA256SUMS file, io.ReadAll failed while draining resp.Body — the connection dropped or a read/timeout error occurred mid-transfer. The checksum content could not be fully retrieved, so downloadChecksumFile aborts and wraps the underlying read error (typically an io.ReadError, unexpected EOF, or context deadline).
Source
Thrown at provisioner/hcp-sbom/packer_release_fetch.go:163
func downloadChecksumFile(ctx context.Context, client *http.Client, url string) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", fmt.Errorf("failed to build request for %s: %w", url, err)
}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("failed to download %s: %w", url, err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("download failed: HTTP %d for %s", resp.StatusCode, url)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed reading response body for %s: %w", url, err)
}
if len(strings.TrimSpace(string(body))) == 0 {
return "", fmt.Errorf("empty response body for %s", url)
}
return string(body), nil
}
func isValidSHA256Hex(s string) bool {
if len(s) != 64 {
return false
}
_, err := hex.DecodeString(s)
return err == nil
}
func expectedZipSHA256FromSums(sumsContent, fileName string) (string, error) {
for _, line := range strings.Split(sumsContent, "\n") {View on GitHub (pinned to eb36e3c3e4)
Solutions
- Simply retry — downloadPackerRelease already retries the full flow 3 times with a 5s delay, and this error is usually transient
- Increase the http.Client timeout (currently 5 minutes in downloadPackerRelease) or the context deadline if on very slow links
- Check for middleboxes (proxy, TLS-inspection firewall, VPN) resetting connections to releases.hashicorp.com and bypass them
- Check server-side logs or HashiCorp status if resets correlate with service incidents
Example fix
// before: client built inline with fixed timeout
client := &http.Client{Timeout: 5 * time.Minute}
// after: larger timeout for constrained networks
client := &http.Client{Timeout: 15 * time.Minute} Defensive patterns
Strategy: retry
Validate before calling
// preflight: confirm the checksums endpoint responds and completes a full small read
resp, err := client.Get(shaSumsURL)
if err != nil {
return fmt.Errorf("checksums endpoint unreachable: %w", err)
}
if resp.StatusCode != http.StatusOK {
_ = resp.Body.Close()
return fmt.Errorf("unexpected status %d probing %s", resp.StatusCode, shaSumsURL)
}
n, err := io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
if err != nil {
return fmt.Errorf("connection to %s unstable (read %d bytes then failed): %w", shaSumsURL, n, err)
} Type guard
// identify read/timeout errors from the body as transient network problems
func isBodyReadError(err error) bool {
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
return true
}
return errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) || errors.Is(err, syscall.ECONNRESET)
} Try / catch
sums, err := downloadChecksumFile(ctx, client, shaSumsURL)
if err != nil {
if isBodyReadError(errors.Unwrap(errors.Unwrap(err))) || isBodyReadError(err) {
return retryErr{err} // transient mid-body disconnect; retry
}
return err
} Prevention
- Keep http.Client and context timeouts generous on slow links so body reads are not cut off
- Bypass or tune TLS-inspection proxies/LBs with aggressive idle timeouts
- Prefer wired/stable network or retry automatically for CI runners on VPNs
- Treat any mid-body disconnect as transient and lean on the 3-try retry with 5s backoff
- Monitor for correlated ECONNRESET patterns pointing at a middlebox rather than random flakiness
When it happens
Trigger: io.ReadAll(resp.Body) returns err after a 200 response for <base>/packer/<v>/packer_<v>_SHA256SUMS — server closed the connection mid-body, TLS record corruption, an idle-timeout reset from a proxy/LB, or the request context expired during the body read.
Common situations: Flaky network or VPN dropping long-lived connections; an aggressive proxy/load balancer idle timeout; context deadline expiring on a slow link; TLS interception appliances resetting streams; transient releases.hashicorp.com connection resets.
Related errors
- request GitHub OIDC token: %w
- failed to download %s: %w
- empty response body for %s
- create GitHub OIDC request: %w
- request GitHub OIDC token: unexpected status %s
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/d840b2b057a33fc6.
Report an issue: GitHub.