hashicorp/terraform · error
Error downloading state: %v
Error message
Error downloading state: %v
What it means
Emitted by remoteClient.Get (backend_state.go:65-68) after ReadCurrent succeeds but StateVersions.Download fails. The current state version metadata includes a DownloadURL; this code fetches the raw state bytes from that (often pre-signed, time-limited) URL. Failure means the metadata was readable but the actual state blob could not be retrieved.
Source
Thrown at internal/backend/remote/backend_state.go:67
var _ Fatal = errorUnlockFailed{}
// Get the remote state.
func (r *remoteClient) Get() (*remote.Payload, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
ctx := context.Background()
sv, err := r.client.StateVersions.ReadCurrent(ctx, r.workspace.ID)
if err != nil {
if err == tfe.ErrResourceNotFound {
// If no state exists, then return nil.
return nil, nil
}
return nil, diags.Append(fmt.Errorf("Error retrieving state: %v", err))
}
state, err := r.client.StateVersions.Download(ctx, sv.DownloadURL)
if err != nil {
return nil, diags.Append(fmt.Errorf("Error downloading state: %v", err))
}
// If the state is empty, then return nil.
if len(state) == 0 {
return nil, nil
}
// Get the MD5 checksum of the state.
sum := md5.Sum(state)
return &remote.Payload{
Data: state,
MD5: sum[:],
}, nil
}
func (r *remoteClient) uploadStateFallback(ctx context.Context, stateFile *statefile.File, state []byte, jsonStateOutputs []byte) error {
options := tfe.StateVersionCreateOptions{View on GitHub (pinned to c9def3e214)
Solutions
- Retry the command immediately — a fresh ReadCurrent yields a fresh signed DownloadURL.
- Allowlist the object-storage egress domain (e.g. *.amazonaws.com) in firewall/proxy alongside the TFC API host.
- Reduce state size / split workspaces if downloads repeatedly hit proxy body-size or timeout limits.
- Check the TFC status page for object-storage incidents.
Example fix
// before: pre-signed URL expired in a slow CI step $ terraform plan Error: Error downloading state: 403 Forbidden // after: retry issues a fresh signed URL $ terraform plan # succeeds on retry
Defensive patterns
Strategy: retry
Validate before calling
// Confirm the workspace's current state version has a usable download URL preflight.
sv, err := r.client.StateVersions.ReadCurrent(ctx, r.workspace.ID)
if err != nil { return err }
if sv.DownloadURL == "" { return errors.New("no download URL available; retry ReadCurrent") } Try / catch
// Re-fetch the (freshly signed) state version then retry the download once.
state, err := r.client.StateVersions.Download(ctx, sv.DownloadURL)
if err != nil {
sv, rerr := r.client.StateVersions.ReadCurrent(ctx, r.workspace.ID)
if rerr == nil {
state, err = r.client.StateVersions.Download(ctx, sv.DownloadURL)
}
}
if err != nil { return nil, diags.Append(fmt.Errorf("Error downloading state: %v", err)) } Prevention
- Minimize the gap between ReadCurrent and Download in automation to avoid signed-URL expiry.
- Allowlist the object-storage domain (e.g. *.amazonaws.com) alongside the TFC API host.
- Retry on transient download failures before surfacing the error.
- Keep state small (split workspaces) to avoid proxy body-size/timeout limits.
When it happens
Trigger: The pre-signed DownloadURL has expired before the request was issued; the object storage backend (S3 etc.) is unavailable or throttling; a network/proxy blocks the storage host distinct from the API host; the URL was revoked because a newer state version superseded this one mid-operation.
Common situations: Long pause between ReadCurrent and Download (e.g. slow CI runner) so the signed URL expires; egress-restricted network that allows app.terraform.io but blocks the object-storage domain; transient S3 5xx; large state file hitting a proxy body-size limit.
Related errors
- Error retrieving state: %v
- error uploading state: %v
- operation timed out
- Failed to read state file from %v: %v
- Failed to read state file attrs from %v: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/e5ea6b06301fea2b.
Report an issue: GitHub.