Skip to main content
DevOps Insightsguides & answers

Terraform · troubleshooting

Error: Inconsistent dependency lock file

.terraform.lock.hcl records exactly which version of each provider the configuration uses. When the configuration asks for a provider the lock file does not have, or for a version range the locked version is outside of, Terraform stops rather than quietly choose. The fix depends on which: a new provider needs a plain terraform init; a changed version constraint needs terraform init -upgrade, which upgrades every provider, not just the one you changed.

Reproduced on Terraform 1.14, . Where the text says “reproduced”, the behaviour was run on that version, not taken from documentation.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 10 sections

Before you start

  • A clone of the repository you can push to, since the fix is an updated .terraform.lock.hcl committed alongside the configuration.
  • The same Terraform version as your pipeline, and network access to the provider registry or your organisation's provider mirror, so terraform init can install providers.
  • The pipeline log of the failing step, to tell a terraform init -lockfile=readonly failure from a terraform plan failure.
  • Agreement from whoever owns provider upgrades before you run terraform init -upgrade, because it can move every provider, not only the one you changed.

Run this first

step 1 of 3
terraform plan -no-color 2>&1 | grep -E 'no version is selected|locked version selection|dependency changes detected'

Look for "no version is selected" (new provider), "locked version selection" (constraint changed), (for the read-only lock in CI, read the init step's log for "Provider dependency changes detected", which plan never prints)

The detail line separates the causes, and the fix differs between them.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

What does the line under the error say?

Cause space

3 of 3 still possible

  • A provider was added and the lock file was not updatedCommon
  • A version constraint now excludes the locked versionCommon
  • CI checks the lock file and the committed one is behindOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Check it with a tool

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    terraform plan -no-color 2>&1 | grep -E 'no version is selected|locked version selection|dependency changes detected'

    The detail line separates the causes, and the fix differs between them.

    Look for "no version is selected" (new provider), "locked version selection" (constraint changed), (for the read-only lock in CI, read the init step's log for "Provider dependency changes detected", which plan never prints)

  2. Step 2

    git status --short -- .terraform.lock.hcl; git log -1 --format='%h %ad' --date=short -- .terraform.lock.hcl

    A lock file that is untracked or ignored means every machine picks its own versions, and this error is the least of it.

    Look for The lock file tracked and committed, and when it last changed

  3. Step 3

    grep -A2 '^provider "' .terraform.lock.hcl

    Shows the locked version and the constraints it was selected under, to compare against required_providers.

    Look for A version outside the constraint now written in configuration

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

A provider was added and the lock file was not updated

Common

Someone added a provider to required_providers - or a module that needs one - and committed the configuration without running terraform init, or without committing the lock file it changed. Every other machine and every pipeline now has a configuration that asks for a provider its lock file has no selection for.

Confirm

terraform plan -no-color 2>&1 | grep 'no version is selected'

One line per provider the lock file is missing

Fix

  • Run a plain terraform init. Reproduced on 1.14, it installs the new provider and keeps every existing selection as it was.
  • Commit the updated .terraform.lock.hcl in the same change as the configuration that needed it.
  • Avoid -upgrade here unless you also mean to upgrade everything else: it re-selects the newest allowed version of every provider.
terraform init && git add .terraform.lock.hcl

Review git diff --cached .terraform.lock.hcl before committing: it should add the new provider and change nothing else.

A version constraint now excludes the locked version

Common

The version argument in required_providers was edited - pinned lower, tightened, or moved to a new major version - and the version in the lock file falls outside it. Terraform will not silently swap the provider: a plain init refuses and says that only -upgrade may select a different version.

Confirm

terraform plan -no-color 2>&1 | grep -E 'locked version selection'

The locked version and the new constraint, side by side

Fix

  • Run terraform init -upgrade, then review the lock file diff. It will show every provider that moved, which can be more than the one whose constraint you edited. -upgrade also re-fetches every module to the newest version its constraint allows, which does not appear in the lock file, so check init's module output too.
  • Plan before applying, and read the plan as a provider upgrade: a new provider version can change how existing resources are read or planned.
  • Commit the lock file with the constraint change.
terraform init -upgrade && git diff -- .terraform.lock.hcl

If more providers moved than intended, tighten their constraints first, then upgrade again.

CI checks the lock file and the committed one is behind

Occasional

The pipeline runs terraform init -lockfile=readonly, which the documentation describes as suppressing lock file changes while still verifying checksums. That is the right setting - it turns a silent dependency change into a failed build - and this error is it working: the configuration needs a provider selection the committed lock file does not contain. Reproduced: "Changes to the required provider dependencies were detected, but the lock file is read-only."

Confirm

git log -5 --name-only --format='%h %ad %s' --date=short -- .terraform.lock.hcl '*.tf'

A configuration change with no matching lock file change

Fix

  • Run terraform init locally - plain, or with -upgrade if a constraint changed - and commit the lock file it produces.
  • Keep -lockfile=readonly in CI. Removing it would make the error go away by letting each run choose its own versions.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Terraform writes down the exact provider versions your configuration uses in a file called .terraform.lock.hcl. This error means the configuration and that file no longer agree, usually because someone added a provider or changed a version requirement without updating the file. Terraform stops instead of guessing, and the right kind of terraform init, followed by committing the file, fixes it.

A provider added without updating the lock file, reproduced

Reproduced with Terraform 1.14.0 and the local backend, with nothing downloaded. The configuration held one terraform_data resource, and its lock file already recorded hashicorp/random 3.6.0, written by terraform init from a local filesystem mirror of placeholder packages: empty stand-ins labelled with real version numbers, never real provider builds and never run, so nothing had to be downloaded. Then hashicorp/null with version = "~> 3.2" was added to required_providers, and terraform plan was run without running init again. The output contained no user, host or path details.

Command

terraform plan

Output

Error: Inconsistent dependency lock file

The following dependency selections recorded in the lock file are
inconsistent with the current configuration:
  - provider registry.terraform.io/hashicorp/null: required by this configuration but no version is selected

To update the locked dependency selections to match a changed configuration,
run:
  terraform init -upgrade

How to read it

  • Each - provider line names one provider that disagrees, by its full address. required by this configuration but no version is selected means the lock file has never recorded it.
  • Had a version constraint changed instead, the line would read locked version selection 3.2.4 doesn't match the updated version constraints "~> 3.3", reproduced the same way.
  • The suggested terraform init -upgrade does more than a new provider needs. Here a plain terraform init added hashicorp/null and left hashicorp/random at 3.6.0, while -upgrade also moved hashicorp/random to 3.7.2, the newest placeholder in the mirror.
  • With no lock file at all, the same error instead ends by suggesting a plain terraform init.
  • In a pipeline running terraform init -lockfile=readonly, the same change fails earlier, at init, with Error: Provider dependency changes detected.

Words used on this page

Provider
A plugin that lets Terraform manage one kind of system, such as a cloud platform, identified by an address like registry.terraform.io/hashicorp/null and installed by terraform init.
Dependency lock file
.terraform.lock.hcl in the root module. For each provider it records the selected version, the constraints it was selected under, and checksums of the package.
Version constraint
The version argument in required_providers, such as ~> 3.2, which limits the provider versions Terraform may use.
Selection
The one version terraform init picked for a provider and wrote to the lock file. Later runs of init reuse it until you add -upgrade.
-upgrade
A terraform init option that ignores existing selections and picks the newest allowed version of every provider, and updates modules too.
-lockfile=readonly
A terraform init option that refuses to change the lock file but still checks package checksums against it. Pipelines use it so dependency changes fail loudly.
Checksum
A fingerprint of a provider package, stored under hashes in the lock file, which Terraform uses to check it installs the same package as before.
What is actually happening

The lock file is Terraform's record of the provider versions this configuration was tested with, plus checksums for each. HashiCorp's documentation says to keep it in version control so that dependency changes go through code review like any other change. Once a provider has a selection recorded there, terraform init re-selects that version every time, even when a newer one has come out.

So the error is not corruption. It means the configuration and the lock file have stopped describing the same thing. Reproduced on Terraform 1.14, there are two common ways to get there, and the detail line says which (a third, on terraform apply <planfile>, means the plan was made with different lock selections: re-plan): a provider was added that the lock file has never seen ("required by this configuration but no version is selected"), or a version constraint was changed so the locked version no longer fits ("locked version selection 3.2.4 doesn't match the updated version constraints").

The message suggests terraform init -upgrade for both, and for the first that is more than you need. Reproduced: after adding a provider, a plain terraform init installed it and left the existing provider exactly where it was locked. -upgrade would not have - the documentation says it upgrades all previously selected plugins to the newest version the constraints allow. In a configuration with several providers, that is a dependency upgrade nobody asked for, landing in a commit about something else.

For the second, a plain init is not enough. Reproduced: it refuses with "must use terraform init -upgrade to allow selection of new versions", and only -upgrade moves the lock.

How to tell this is your problem
WhereWhat you see
terraform plan / applyError: Inconsistent dependency lock file
the detail lineprovider registry.terraform.io/hashicorp/null: required by this configuration but no version is selected
the detail linelocked version selection 3.2.4 doesn't match the updated version constraints "~> 3.3"
terraform initError: Failed to query available provider packages ... must use terraform init -upgrade to allow selection of new versions
CI, terraform init -lockfile=readonlyError: Provider dependency changes detected

How to know it is actually fixed

  • terraform plan runs without the lock file error.
  • The lock file diff changes only the providers you meant to change.
  • In CI, terraform init -lockfile=readonly passes with the committed lock file.

Stopping it happening again

  • Commit .terraform.lock.hcl, and review its diff like code - HashiCorp's own recommendation.
  • Run init -lockfile=readonly in CI, so a configuration that needs a lock change fails there rather than drifting.
  • Add providers with a plain terraform init; keep -upgrade for deliberate, reviewed upgrades.
  • If providers come from a mirror or are used on several platforms, pre-populate checksums with terraform providers lock -platform=..., as the documentation describes, instead of letting each machine add its own.

Security considerations

  • HashiCorp describes the lock file's checksums as trust on first use. Review every new provider block and every changed hashes list in a pull request as carefully as code, because whatever the first terraform init installed is what later runs will accept.
  • Keep terraform init -lockfile=readonly in your pipeline. It refuses lock file changes and still verifies checksums against the recorded ones, so a pipeline cannot quietly pick up a different provider build.
  • Do not delete .terraform.lock.hcl or stop committing it to make the error go away. With no recorded selection, terraform init picks the newest allowed version and records new checksums, so you lose both the pin and the checksums you reviewed.
  • When a provider is first installed from a filesystem or network mirror, Terraform can record the checksum only for the platform you ran terraform init on, and cannot check the registry's signed checksums for the others; terraform init from a filesystem mirror reported (unauthenticated) in this reproduction. Where you can, create lock entries from the origin registry with terraform providers lock.
  • terraform init -upgrade can bring in new provider and module code that then runs with your cloud credentials. Make it its own reviewed change, read the lock file diff and init's module output, and plan before applying.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it