Terraform Lock File Viewer

Read the lock file and get the answer to the question it usually raises: why does init work here and fail in CI? It is almost always which kind of hash is recorded.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Read. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

Locally computed hashes only

Tied to the machine that ran init, so another platform fails the checksum

provider "registry.terraform.io/hashicorp/aws" {
  version     = "5.31.0"
  constraints = "~> 5.0"
  hashes      = ["h1:abc"]
}

A version its own constraint excludes

The constraint was tightened without re-running init, so the two disagree

provider "registry.terraform.io/hashicorp/aws" {
  version     = "4.67.0"
  constraints = "~> 5.0"
  hashes      = ["zh:abc", "h1:def"]
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Gitignoring the lock file

    It is the record of which provider versions were actually used. Without it two people applying the same configuration can get different providers, and nothing shows why the results differ.

    Instead:Commit it. Check that .gitignore says .terraform/ with a trailing slash rather than .terraform*.

  2. Running init on one OS and expecting CI to work

    init records h1 hashes only for the platform it ran on, so a Linux runner reading a Mac-written lock file fails the checksum. The error looks like a supply-chain warning.

    Instead:Run terraform providers lock with a -platform flag for every platform you use, and commit the result.

  3. Deleting the lock file to fix a checksum error

    It removes the evidence and the pinning at once, so the next init silently selects whatever is newest and the problem comes back on the next machine.

    Instead:Add the missing platform with terraform providers lock -platform=... instead.

There are two kinds of hash in here and only one of them travels

This one distinction explains the checksum errors that appear when a different machine runs init on a configuration that has worked for months.

zh comes from the registry and covers every platform

A zh entry is the SHA256 of an official release archive, taken from the registry's signed checksum list. Terraform records all of them when it can verify the signature, so a lock file with zh hashes works on any platform.

h1 is computed locally and covers only what was installed

An h1 entry is a hash of the extracted package, computed on the machine that ran init. It exists only for the platforms that machine downloaded. A lock file with h1 entries and no zh entries is tied to the operating system that wrote it, and init elsewhere fails with a checksum mismatch that reads like tampering.

The fix is providers lock with explicit platforms

terraform providers lock -platform=linux_amd64 -platform=darwin_arm64 -platform=windows_amd64 records hashes for each, and the result is committed. Run it whenever a provider is added or upgraded, listing whatever your CI runners and your laptops actually are.

This file must be committed

It is the only record of which provider versions were used, and the only thing that stops two people getting different providers from identical configuration. The usual reason it is missing is a .gitignore with .terraform* rather than .terraform/, which catches this file as collateral.

An entry with no constraints line was inferred

Terraform worked the provider out from resource type names rather than being told. It works, and nothing in the configuration states which versions are acceptable, so the next init can select anything.

A locked version outside its own constraint blocks planning

Somebody tightened the constraint without re-running init, so the two disagree. terraform init -upgrade selects a version inside the new constraint and rewrites the entry.

More terraform tools

Terraform Validator & Formatter Does it parse, and is it formatted? Terraform dynamic Block Generator It is ingress.value, not each.value Terraform check and precondition Generator A failed check does not stop the apply Terraform variables.tf Generator From the var. references you already wrote Terraform Unused Declaration Linter Dead variables, locals and data sources Terraform Atlantis YAML Generator when_modified misses your modules Terraform Function Tester and HCL Console terraform console, in a tab Terraform for Expression Tester Where do the keys collide? Terraform Interpolation Tester null becomes an empty string Terraform templatefile Tester Render it before you apply it Terraform Resource Count Calculator How many objects, not how many blocks Terraform count to for_each Converter With the moved blocks it needs Terraform moved Block Generator Rename without destroying Terraform state mv Command Builder No plan, no undo Terraform target Flag Builder And why to stop using it Terraform outputs.tf Generator Outputs are not sensitive by default Terraform Remote State Data Source Generator It grants read of the whole state Terraform Provider Block Generator docker is not hashicorp/docker Terraform .gitignore Generator and Checker .terraform* eats the lock file Terraform to OpenTofu Migration Checker The state is the part to watch Terraform tfvars to JSON Converter The JSON file wins Terraform Version Constraint Parser What ~> actually allows Terraform Resource Address Parser Quote it before the shell eats it Terraform cidrsubnet Calculator newbits is added, not the target Terraform Import Block Generator The id is not the name Terraform Variables Checker A missing value hangs CI Terraform tfvars to Env Vars Converter Lists and maps have to be JSON Terraform Deprecated Syntax Checker What a current Terraform rejects Terraform State File Viewer Read it without uploading it Terraform Plan JSON Viewer It is not redacted Terraform HCL to JSON Converter And what the conversion loses Terraform Module Source Validator version only works for the registry Terraform Backend Config Decoder Is state actually locked? Terraform Naming Convention Validator A hyphen makes a resource unreferenceable

Elsewhere on the site