hashicorp/terraform · error

provider : version constraints don't match the locked…

Error message

provider %s: version constraints %q don't match the locked version selection %s

What it means

The locked version does not satisfy the current version constraints, but the constraint strings in the config and lock file are identical (the default/else branch of the switch). This means the lock file records a version that violates the very constraints it claims to satisfy — typically caused by manual editing of the lock file, or by a lock file written by a buggy or older Terraform version.

Solutions

  1. Run terraform init --upgrade to regenerate a consistent lock file from scratch.
  2. If the lock file was manually edited, revert it from version control and re-run terraform init.
  3. Delete .terraform.lock.hcl and run terraform init to produce a fresh lock file.
  4. Verify no merge conflict artifacts remain in the lock file.

Example fix

# before — manually edited lock file with incompatible version
git checkout -- .terraform.lock.hcl  # if corrupted
terraform plan  # → error

# after — regenerate from clean state
rm .terraform.lock.hcl
terraform init
terraform plan
Defensive patterns

Strategy: validation

Validate before calling

// Detect lock file inconsistency before plan
// Shell pre-check:
//   terraform init -lockfile=readonly  # catches internal inconsistency
// If corrupt:
//   rm .terraform.lock.hcl && terraform init

Prevention

When it happens

Trigger: The lock file's provider version entry doesn't satisfy the constraints recorded alongside it in the same lock file, and the constraints haven't changed from config. Triggered by hand-editing .terraform.lock.hcl to pin an incompatible version, or by lock file corruption.

Common situations: Developer manually edits .terraform.lock.hcl to force a specific version that violates the constraints. Lock file generated by an older Terraform version with a resolver bug. Partial write or merge conflict left the lock file in an inconsistent state. Lock file was copied from another project with different constraints.

Related errors


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

Appendix: source

Thrown at internal/configs/config.go:314

		selectedVersion := lock.Version()
		allowedVersions := providerreqs.MeetingConstraints(constraints)
		log.Printf("[TRACE] Config.VerifyDependencySelections: provider %s has %s to satisfy %q", providerAddr, selectedVersion.String(), providerreqs.VersionConstraintsString(constraints))
		if !allowedVersions.Has(selectedVersion) {
			// The most likely cause of this is that the author of a module
			// has changed its constraints, but this could also happen in
			// some other unusual situations, such as the user directly
			// editing the lock file to record something invalid. We'll
			// distinguish those cases here in order to avoid the more
			// specific error message potentially being a red herring in
			// the edge-cases.
			currentConstraints := providerreqs.VersionConstraintsString(constraints)
			lockedConstraints := providerreqs.VersionConstraintsString(lock.VersionConstraints())
			switch {
			case currentConstraints != lockedConstraints:
				errs = append(errs, fmt.Errorf("provider %s: locked version selection %s doesn't match the updated version constraints %q", providerAddr, selectedVersion.String(), currentConstraints))
			default:
				errs = append(errs, fmt.Errorf("provider %s: version constraints %q don't match the locked version selection %s", providerAddr, currentConstraints, selectedVersion.String()))
			}
		}
	}

	// Return multiple errors in an arbitrary-but-deterministic order.
	sort.Slice(errs, func(i, j int) bool {
		return errs[i].Error() < errs[j].Error()
	})

	return errs
}

// ProviderRequirements searches the full tree of modules under the receiver
// for both explicit and implicit dependencies on providers.
//
// The result is a full manifest of all of the providers that must be available
// in order to work with the receiving configuration.
//

View on GitHub (pinned to d32a084675)