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
- Run terraform init --upgrade to regenerate a consistent lock file from scratch.
- If the lock file was manually edited, revert it from version control and re-run terraform init.
- Delete .terraform.lock.hcl and run terraform init to produce a fresh lock file.
- 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
- Never hand-edit .terraform.lock.hcl — always use terraform init.
- Add .terraform.lock.hcl to code review checks — reject manual modifications.
- Run terraform init -lockfile=readonly in CI to detect corruption.
- If merging branches, resolve lock file conflicts by deleting and re-initializing rather than hand-merging.
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
- provider : required by this configuration but no version is…
- failed to determine the configuration's provider…
- provider : locked version selection doesn't match the…
- address must be HTTP or HTTPS
- attempted to encode a malformed backend state file…
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)