hashicorp/terraform · error
Remote workspace Terraform version %q does not match local T
Error message
Remote workspace Terraform version %q does not match local Terraform version %q
What it means
A safety fallback guard at backend.go:870-876 that aborts state access when the remote workspace's recorded Terraform version differs from the local terraform binary version and ignoreVersionConflict has not been set. It exists to prevent state from being written by a mismatched engine version, which could corrupt or upgrade the state format unexpectedly. The pseudo-version "latest" is explicitly skipped so it never trips this check.
Source
Thrown at internal/cloud/backend.go:874
}
_, err = b.client.Workspaces.AddTagBindings(context.Background(), workspace.ID, options)
}
if err != nil {
return nil, diags.Append(fmt.Errorf("error updating workspace %q tags: %w", name, err))
}
}
// This is a fallback error check. Most code paths should use other
// mechanisms to check the version, then set the ignoreVersionConflict
// field to true. This check is only in place to ensure that we don't
// accidentally upgrade state with a new code path, and the version check
// logic is coarser and simpler.
if !b.ignoreVersionConflict {
// Explicitly ignore the pseudo-version "latest" here, as it will cause
// plan and apply to always fail.
if remoteTFVersion != tfversion.String() && remoteTFVersion != "latest" {
return nil, diags.Append(fmt.Errorf("Remote workspace Terraform version %q does not match local Terraform version %q", remoteTFVersion, tfversion.String()))
}
}
return &State{tfeClient: b.client, organization: b.Organization, workspace: workspace, enableIntermediateSnapshots: false}, diags
}
// Operation implements backendrun.OperationsBackend.
func (b *Cloud) Operation(ctx context.Context, op *backendrun.Operation) (*backendrun.RunningOperation, error) {
// Retrieve the workspace for this operation.
w, err := b.fetchWorkspace(ctx, b.Organization, op.Workspace)
if err != nil {
return nil, err
}
// Terraform remote version conflicts are not a concern for operations. We
// are in one of three states:
//
// - Running remotely, in which case the local version is irrelevant;View on GitHub (pinned to c9def3e214)
Solutions
- Align the versions: update the workspace's Terraform Version in HCP Terraform / TFE UI to match your local binary, OR downgrade/upgrade the local binary to match the workspace.
- If the mismatch is intentional (e.g. worker forcing local ops), call IgnoreVersionConflict() before accessing state, or run through the Operation() path which does this automatically.
- Set the workspace version to 'latest' so the check is bypassed (note: not recommended for apply/plan per the comment at backend.go:871-872).
Example fix
// before: local 1.7.x, workspace pinned to 1.6.x -> error // fix A: update workspace version in UI to 1.7.x // fix B: explicit ignore when forcing local // (code path) b.IgnoreVersionConflict() is invoked by Operation(); // for direct StateMgr use ensure versions match.
Defensive patterns
Strategy: validation
Validate before calling
// Compare local vs remote version before any state access.
func versionsAligned(local, remote string) bool {
return remote == "latest" || remote == local
}
// Call b.IgnoreVersionConflict() instead if mismatch is intentional,
// or update the workspace version in HCP/TFE to match runtime.Version(). Prevention
- Pin workspace Terraform Version to the exact CLI version used in CI.
- In CI, install the same Terraform version the workspace is configured for.
- Use Operation() paths (plan/apply) which auto-ignore version conflicts rather than direct StateMgr.
When it happens
Trigger: Calling StateMgr/LocalRun when remoteTFVersion != tfversion.String() and remoteTFVersion != "latest" and b.ignoreVersionConflict == false. Happens when a workspace is pinned to e.g. 1.6.x but the local binary is 1.7.x (or vice-versa).
Common situations: Upgrading the local Terraform CLI without updating the workspace's Terraform Version setting in HCP/TFE. Downgrading locally for debugging while the workspace stays on a newer version. CI runners auto-pulling latest terraform while workspaces are pinned. The Operation() path (backend.go:897) calls IgnoreVersionConflict(), so this mainly bites state-only access (LocalRun / StateMgr) before an operation.
Related errors
- Failed to retrieve workspace %s: %v
- backend does not support key/value tags. Try using key-only
- error loading state: %w
- failed checking for existing remote state: %s
- failed to generate initial lineage: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/79d76f703be7183f.
Report an issue: GitHub.