What the lockfile is
.terraform.lock.hcl is a file in the project root where terraform
records: "for the current configuration I downloaded the AWS provider
version 5.62.0 with these hashes." The lockfile appears after the first
[[tf-init|terraform init]] and is then updated by the rules below.
Its purpose is determinism. Without a lockfile, two engineers or CI can download different minor versions of a plugin from the same code and end up with different plans. With a lockfile, everyone gets the same build until someone bumps it explicitly.
Example contents:
provider "registry.terraform.io/hashicorp/aws" {version = "5.62.0"
constraints = "~> 5.60"
hashes = [
"h1:abc123...",
"h1:def456...",
"zh:0123...",
"zh:4567...",
]
}
versionis the exact installed version.constraintsis the expression fromrequired_providers. The lockfile remembers it so that oninit -upgradeit looks for a new version within the same constraint.hashesare two kinds of hashes.h1:is the hash of the whole zip archive.zh:is the hash of a specific binary for one platform.
When the lockfile changes
- First
terraform initcreates it from scratch, with the version set to the latest one that fits the constraint. terraform initwith no flags: if the lockfile already has an entry, terraform tries to honor it. If the hashes do not match, it fails.terraform init -upgradegoes to the registry for fresh versions within the same constraint and rewrites the lockfile.- The
required_providersblock changes: if you add a provider, change a constraint, or change a source, the nextinitwrites or rewrites the matching blocks. terraform providers lockis a deliberate update of the hashes for several platforms (see below).
No command ever edits the lockfile "by accident." If the file changed, one of these scenarios happened.
Multi-platform hashes
When init runs on macOS, the lockfile gets the hashes of binaries for
darwin_arm64 or darwin_amd64. When the same project later runs in a
Linux CI, terraform on that platform will not find the hash it needs and
will fail.
The fix is to add the hashes for every platform you need up front:
terraform providers lock \
-platform=linux_amd64 \
-platform=linux_arm64 \
-platform=darwin_amd64 \
-platform=darwin_arm64
The command goes to the registry for the hashes of each platform and appends them to the lockfile. One run is enough when you set up the project, or when you add a new platform to the command.
To commit or not
Commit it. The lockfile is part of the project's source of truth,
on a par with the .tf files. Without it you lose the main benefit:
repeatability.
In .gitignore you list only .terraform/ (the provider cache), not
.terraform.lock.hcl. A common beginner mistake is to add *.lock to
gitignore and hide the lockfile. After that, complaints of "it works on
my machine but not in CI" become regular.
What to do on a hash error
The error text from init:
Error: Failed to install provider
Error while installing hashicorp/aws v5.62.0: the local package for
registry.terraform.io/hashicorp/aws 5.62.0 doesn't match any of the
checksums previously recorded in the dependency lock file
Causes and fixes:
initran on a new platform. The fix isterraform providers lock -platform=...(see above), then commit the updated lockfile.- You changed the provider version without
-upgrade. The fix isterraform init -upgrade. - A registry mirror served a different binary. This is serious. Check whether the provider was swapped in your corporate mirror.
Lockfile conflict on merge
Two people on one branch changed required_providers. They got a git
conflict in .terraform.lock.hcl. What to do:
- Do not try to merge the hash blocks by hand. They are fragile.
- Take either version (or
git checkout --ours/--theirs). - Run
terraform init -upgrade. It rewrites the lockfile for the current HCL. - Commit the result.
Pitfalls
- The lockfile does not block major bumps on
init -upgrade. If the constraint is>= 5.0(with no upper bound),-upgradewill happily move you to 6.x. To prevent that, write pessimistic constraints like~> 5.60(see tf-version-constraints). - The lockfile does not pin modules. Only providers. Modules are
cached in
.terraform/modules/without hashes, and module versions have to be controlled through a [[tf-init-modules|version constraint in the module block]]. .terraform.lock.hclis edited only by tooling. Do not edit it by hand. If you really must, delete it and runinit -upgrade.