hashicorp/terraform · error
failed to load state
Error message
failed to load state: %w
What it means
Thrown by GetRootOutputValues during the fallback path: when an output lacks DetailedType (indicating pre-terraform-1.3.0 state), the code calls s.RefreshState() to read the full state and extract outputs the old way. This error wraps a RefreshState failure, meaning the full state could not be downloaded and parsed. The %w preserves the underlying refresh error (which itself may be a getStatePayload/read failure).
Solutions
- Address the underlying RefreshState error first (check the wrapped error for network/auth/download details)
- Upgrade the workspace state to a modern format by running terraform apply once successfully with terraform >= 1.3.0 to populate DetailedType and eliminate the fallback path
- Verify the authenticated identity has permission to read the full state (the fallback requires higher authorization than the outputs-only path)
Defensive patterns
Strategy: validation
Validate before calling
// Before calling GetRootOutputValues on a legacy workspace, refresh state once
// to confirm the full-state-read path works:
if err := state.RefreshState(); err != nil {
return fmt.Errorf("full state read will fail for legacy output fallback: %w", err)
} Try / catch
outputs, err := state.GetRootOutputValues(ctx)
if err != nil && strings.Contains(err.Error(), "failed to load state") {
// The fallback path failed; the underlying RefreshState error is wrapped.
// Address the root cause (network/auth) then retry.
return nil, fmt.Errorf("legacy output fallback failed during state load: %w", err)
}
return outputs, err Prevention
- Upgrade legacy workspaces (pre-1.3.0 state) by running a successful apply with terraform >= 1.3.0 to populate DetailedType
- Ensure the service account has full-state-read permission since the legacy fallback requires it
- Avoid mixing very old state formats with modern terraform versions without an intermediate upgrade apply
When it happens
Trigger: A workspace whose state was last written by terraform < 1.3.0 (no DetailedType on outputs) AND the current RefreshState call fails due to network, auth, or download issues; the fallback path compounds any getStatePayload error (errors 525/526) with this wrapper.
Common situations: Legacy workspace never upgraded since pre-1.3.0, combined with a transient network issue or token expiry; migrating an old workspace to a new TFE instance where the service account lacks full-state-read permission needed by the fallback.
Related errors
- canceled reading current outputs
- could not decode output
- could not interpret output
- could not interpret value
- could not marshal output
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/54c2100889e75fbc.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloud/state.go:586
return nil, fmt.Errorf("current outputs were not ready to be read within the deadline. Please try again")
case context.Canceled:
return nil, fmt.Errorf("canceled reading current outputs")
}
return nil, fmt.Errorf("could not read state version outputs: %w", err)
}
result := make(map[string]*states.OutputValue)
for _, output := range so.Items {
if output.DetailedType == nil {
// If there is no detailed type information available, this state was probably created
// with a version of terraform < 1.3.0. In this case, we'll eject completely from this
// function and fall back to the old behavior of reading the entire state file, which
// requires a higher level of authorization.
log.Printf("[DEBUG] falling back to reading full state")
if err := s.RefreshState(); err != nil {
return nil, fmt.Errorf("failed to load state: %w", err)
}
state := s.State()
if state == nil {
// We know that there is supposed to be state (and this is not simply a new workspace
// without state) because the fallback is only invoked when outputs are present but
// detailed types are not available.
return nil, ErrStateVersionUnauthorizedUpgradeState
}
return state.RootOutputValues, nil
}
if output.Sensitive {
// Since this is a sensitive value, the output must be requested explicitly in order to
// read its value, which is assumed to be present by callers
sensitiveOutput, err := s.tfeClient.StateVersionOutputs.Read(ctx, output.ID)
if err != nil {View on GitHub (pinned to d32a084675)