hashicorp/terraform · error
Failed to read remote state: %s
Error message
Failed to read remote state: %s
What it means
After the HTTP backend received an acceptable status code (200) for a Get(), reading the response body via io.Copy failed. This is a transport-level failure mid-stream rather than an HTTP protocol error; the underlying connection dropped or was reset while the body was being copied into a buffer.
Source
Thrown at internal/backend/remote-state/http/client.go:174
// Handled after
case http.StatusNoContent:
return nil, diags
case http.StatusNotFound:
return nil, diags
case http.StatusUnauthorized:
return nil, diags.Append(fmt.Errorf("HTTP remote state endpoint requires auth"))
case http.StatusForbidden:
return nil, diags.Append(fmt.Errorf("HTTP remote state endpoint invalid auth"))
case http.StatusInternalServerError:
return nil, diags.Append(fmt.Errorf("HTTP remote state internal server error"))
default:
return nil, diags.Append(fmt.Errorf("Unexpected HTTP response code %d", resp.StatusCode))
}
// Read in the body
buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, resp.Body); err != nil {
return nil, diags.Append(fmt.Errorf("Failed to read remote state: %s", err))
}
// Create the payload
payload := &remote.Payload{
Data: buf.Bytes(),
}
// If there was no data, then return nil
if len(payload.Data) == 0 {
return nil, diags
}
// Check for the MD5
if raw := resp.Header.Get("Content-MD5"); raw != "" {
md5, err := base64.StdEncoding.DecodeString(raw)
if err != nil {
return nil, diags.Append(fmt.Errorf(
"Failed to decode Content-MD5 '%s': %s", raw, err))View on GitHub (pinned to c9def3e214)
Solutions
- Retry the Terraform command; transient mid-stream resets usually succeed on the next attempt.
- If recurring on large state, raise the read/idle timeouts on the reverse proxy in front of the state server.
- Verify network stability to the state endpoint (large download test via curl).
- Inspect TF_LOG=DEBUG output for the exact io error (e.g. 'connection reset by peer', 'unexpected EOF').
Defensive patterns
Strategy: retry
Try / catch
// Wrap remote-state reads and retry on transient io errors
for i := 0; i < 3; i++ {
payload, diags := client.Get()
if !diags.HasErrors() {
return payload, nil
}
// transient read errors (connection reset, EOF) are retryable
time.Sleep(backoff(i))
}
return nil, lastDiags Prevention
- Place the state server behind a proxy with read timeouts larger than the largest expected state download.
- Prefer a managed object store (S3/GCS) over a hand-rolled HTTP endpoint for large states.
- Monitor network stability between Terraform runners and the state endpoint.
When it happens
Trigger: A GET to the state URL returns 200 but the connection is closed or reset before the full body is delivered, causing io.Copy(resp.Body) to return a non-nil error at client.go:173.
Common situations: An intermediary proxy/load balancer with a short read timeout cutting the connection on large state files; flaky network or VPN dropping packets; the state server crashing mid-response; TLS renegotiation or keep-alive closure during a long download.
Related errors
- HTTP error: %d
- failed to read remote state: %s
- resp.Status
- resp.Status
- Failed to read state file from %v: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/308f8d951b893317.
Report an issue: GitHub.