hashicorp/terraform · error

Remote workspace Terraform version

Error message

Remote workspace Terraform version %q does not match local Terraform version %q

What it means

Fallback Terraform-version conflict guard. When b.ignoreVersionConflict is false and the remote workspace's pinned TerraformVersion differs from the local CLI version (and is not the pseudo-version 'latest'), the backend refuses to proceed to avoid silently upgrading state with an incompatible version.

Solutions

  1. Align versions: set the workspace's Terraform Version in the TFC/TFE UI (Settings -> Version) to match your local CLI.
  2. If intentional, bypass the guard with 'terraform init/plan/apply -ignore-remote-version' (sets b.ignoreVersionConflict=true).
  3. Pin the local CLI to the workspace's version using tfenv / .terraform-version.

Example fix

# before: workspace pinned to 1.5.7, local CLI is 1.6.0
# option A - align workspace (in TFC UI: Settings > General > Terraform Version = 1.6.0)
# option B - bypass locally
terraform plan -ignore-remote-version
Defensive patterns

Strategy: validation

Validate before calling

// Compare local vs workspace TF version before running, to fail with a clearer message.
func versionsAligned(local, remote string) bool {
    return remote == "latest" || remote == local
}
// or pass -ignore-remote-version when mismatch is intentional

Prevention

When it happens

Trigger: workspace.TerraformVersion != tfversion.String() AND != "latest" AND b.ignoreVersionConflict == false. Happens right after workspace fetch in the state/client construction path.

Common situations: Local Terraform upgraded (e.g. 1.5 -> 1.6) but the TFC workspace is pinned to the older version; developer downgraded locally; CI image switched TF version while the workspace stayed pinned; workspace explicitly set to a fixed version in the UI.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/077248d03535ed3f. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/remote/backend.go:701

		}

		workspace, err = b.client.Workspaces.Create(context.Background(), b.organization, options)
		if err != nil {
			return nil, diags.Append(fmt.Errorf("Error creating workspace %s: %v", 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 {
		wsv := workspace.TerraformVersion
		// Explicitly ignore the pseudo-version "latest" here, as it will cause
		// plan and apply to always fail.
		if wsv != tfversion.String() && wsv != "latest" {
			return nil, diags.Append(fmt.Errorf("Remote workspace Terraform version %q does not match local Terraform version %q", workspace.TerraformVersion, tfversion.String()))
		}
	}

	client := &remoteClient{
		client:       b.client,
		organization: b.organization,
		workspace:    workspace,

		// This is optionally set during Terraform Enterprise runs.
		runID: os.Getenv("TFE_RUN_ID"),
	}

	return &remote.State{
		Client: client,

		// client.runID will be set if we're running in a HCP Terraform
		// or Terraform Enterprise remote execution environment, in which
		// case we'll disable intermediate snapshots to avoid extra storage

View on GitHub (pinned to d32a084675)