hashicorp/terraform · error
unable to read 'content' from response
Error message
unable to read 'content' from response: %w
What it means
Head and Get both succeeded (headers and an open body stream were returned), but io.ReadAll failed while streaming the body. The connection dropped mid-download, the server reset the stream, or the context was cancelled during the read.
Solutions
- Retry the Get — the state file did not change, only the stream broke.
- Stabilize the network path for large transfers (wired CI runner, less lossy route).
- Reduce state size (split into workspaces, prune stale resources) to make transfers more resilient.
- Confirm the HTTP client read timeout exceeds the slowest expected download.
Example fix
// before: single shot Get on a flaky link
payload, err := client.Get()
// after: retry read failures specifically
for i := 0; i < 3; i++ {
payload, err = client.Get()
if err == nil { break }
if strings.Contains(err.Error(), "unable to read 'content'") {
time.Sleep(backoff(i)); continue
}
break
} Defensive patterns
Strategy: retry
Type guard
func isBodyReadErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "unable to read 'content'")
} Try / catch
// Read-content failures are transient; retry the whole Get
for i := 0; i < 3; i++ {
payload, err := c.Get()
if err == nil { return payload, nil }
if !isBodyReadErr(err) { return nil, err }
time.Sleep(backoff(i))
} Prevention
- Use a stable, low-loss network path for large state downloads.
- Keep the HTTP client read timeout above the slowest expected transfer.
- Reduce state size so partial-stream failures are less likely.
- Monitor download retry counts as a leading indicator of network issues.
When it happens
Trigger: Server or proxy closed the connection mid-stream; client context cancelled; truncated response; socket read timeout hit during a large state download.
Common situations: Large state files over flaky networks; proxy buffering timeouts; CI runners with aggressive idle-read timeouts; the connection died between receiving headers and the full body.
Related errors
- failed to access object HttpStatusCode
- failed to access object
- failed to read existing lock file content
- failed to upload part
- can not read private key from
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/4a3276aa87d56273.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/oci/client.go:107
getRequest.OpcSseCustomerKeySha256 = common.String(c.SSECustomerKeySHA256)
getRequest.OpcSseCustomerAlgorithm = common.String(c.SSECustomerAlgorithm)
}
// Get object from OCI
getResponse, err := c.objectStorageClient.GetObject(ctx, getRequest)
if err != nil {
var ociErr common.ServiceError
if errors.As(err, &ociErr) {
return nil, fmt.Errorf("failed to access object HttpStatusCode: %d\nOpcRequestId: %s\n message: %s\n ErrorCode: %s", ociErr.GetHTTPStatusCode(), ociErr.GetOpcRequestID(), ociErr.GetMessage(), ociErr.GetCode())
}
return nil, fmt.Errorf("failed to access object '%s' in bucket '%s': %w", c.path, c.bucketName, err)
}
defer getResponse.Content.Close()
// Read object content
contentArray, err := io.ReadAll(getResponse.Content)
if err != nil {
return nil, fmt.Errorf("unable to read 'content' from response: %w", err)
}
// Compute MD5 hash
md5Hash := getResponse.ContentMd5
if md5Hash == nil || len(*md5Hash) == 0 {
md5Hash = getResponse.OpcMultipartMd5
}
// Construct payload
payload := &remote.Payload{
Data: contentArray,
MD5: []byte(*md5Hash),
}
// Return an error instead of `nil, nil` if the object is empty
if len(payload.Data) == 0 {
return nil, fmt.Errorf("object %q is empty", c.path)
}
View on GitHub (pinned to d32a084675)