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

  1. Address the underlying RefreshState error first (check the wrapped error for network/auth/download details)
  2. 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
  3. 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

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


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)