Fix Terraform "Inconsistent Dependency Lock File" Error

Tested on Ubuntu 26.04 LTS (Resolute Raccoon)
Package terraform 1.15.8-1
hashicorp/local 2.5.0 and 2.9.0
hashicorp/random 3.9.0
Applies to Any host with Terraform installed
Lab environment Single Ubuntu VM with Terraform — Terraform lab environment on Ubuntu
Privilege Normal user
Scope Troubleshooting Terraform Inconsistent dependency lock file — configuration versus .terraform.lock.hcl mismatch, no version is selected errors, terraform init versus init -upgrade, saved plan apply failures, CI artifact consistency, verify workflow, and lock file deletion guidance. Does not cover module source pinning depth, cloud provider credentials, or manual tfstate JSON editing.
Related guides Provider version constraints and lock file
terraform init
terraform plan
Terraform CI/CD
Terraform troubleshooting

Inconsistent dependency lock file means Terraform sees a mismatch between what your configuration requires and what .terraform.lock.hcl records. The lock file is not optional decoration — it is the bridge between declared constraints and the provider packages terraform init installs.

text
configuration (required_providers)
.terraform.lock.hcl (selected versions + checksums)
installed providers (.terraform/providers/)
saved plan (-out=tfplan, frozen dependency context)

When configuration, the provider lock selections, or a saved plan disagree, Terraform can stop with an Inconsistent dependency lock file error. Missing installed providers normally require re-running terraform init.

Each scenario uses its own directory under ~/terraform-labs/terraform-inconsistent-dependency-lock-file/. Examples use hashicorp/local and hashicorp/random only.

NOTE
Run terraform init after you change required_providers. Commit .terraform.lock.hcl with root Terraform configurations kept in version control so teammates and CI resolve the same provider versions.

What Inconsistent dependency lock file means

Terraform evaluates three related artifacts together:

Artifact Role
required_providers in configuration Declares which plugins the module needs and allowed version ranges
.terraform.lock.hcl Records the version init selected and package checksums
Installed plugins under .terraform/providers/ Binaries used at plan and apply time

.terraform.lock.hcl currently records provider selections; module versions are resolved separately from their configured source/version constraints.

A saved plan file also embeds the dependency context from the moment you ran terraform plan -out=tfplan. Applying that file later requires the same configuration and lock selections.

The error text usually names the mismatch directly — a provider required but no version is selected, a locked version that does not match updated constraints, or a plan file created with different dependency selections.


Case 1: Provider requirement changed without init

Add a new provider to configuration but skip terraform init. Terraform knows random is required while the lock file has no selection for it.

bash
mkdir -p ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/config-mismatch-new-provider
cd ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/config-mismatch-new-provider

Start with only hashicorp/local:

bash
cat > versions.tf <<'EOF'
terraform {
  required_version = ">= 1.12.0"

  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }
}
EOF

Add a minimal local_file resource for the first scenario:

bash
cat > main.tf <<'EOF'
resource "local_file" "demo" {
  content  = "lock lab"
  filename = "${path.module}/demo.txt"
}
EOF

Initialize and create the lock file:

bash
terraform init -input=false
output
- Installing hashicorp/local v2.9.0...
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above.

Add hashicorp/random to required_providers and declare a resource, but do not run init yet:

bash
cat > versions.tf <<'EOF'
terraform {
  required_version = ">= 1.12.0"

  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.6"
    }
  }
}
EOF

Declare a random_id alongside the existing file resource:

bash
cat >> main.tf <<'EOF'

resource "random_id" "x" {
  byte_length = 4
}
EOF

Plan surfaces the lock mismatch:

bash
terraform plan -no-color
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/random: required by this configuration but no version is selected

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

For a newly added provider, plain terraform init is enough — Terraform reuses existing lock entries and adds the missing one:

bash
terraform init -input=false
output
- Reusing previous version of hashicorp/local from the dependency lock file
- Finding hashicorp/random versions matching "~> 3.6"...
- Installing hashicorp/random v3.9.0...

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file.

local stayed on v2.9.0; only random was added. Commit that lock diff with the configuration change.


Case 2: Version constraint conflicts with the lock file

Changing a constraint without updating the lock produces a different error — the lock still pins a version outside the new range.

bash
mkdir -p ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/constraint-changed
cd ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/constraint-changed

Initialize with ~> 2.5 (locks v2.9.0 in this lab):

bash
cat > versions.tf <<'EOF'
terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }
}
EOF

Add a local_file for the constraint-change lab:

bash
cat > main.tf <<'EOF'
resource "local_file" "demo" {
  content  = "constraint lab"
  filename = "${path.module}/demo.txt"
}
EOF

Initialize so the lock file records local v2.9.0:

bash
terraform init -input=false

Tighten the constraint to an exact older release that conflicts with the locked selection:

bash
cat > versions.tf <<'EOF'
terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "= 2.5.0"
    }
  }
}
EOF

Plan reports the locked version no longer matches:

bash
terraform plan -no-color
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/local: locked version selection 2.9.0 doesn't match the updated version constraints "2.5.0"

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

Here you deliberately changed constraints — use init -upgrade so Terraform re-resolves within the new rule:

bash
terraform init -upgrade -input=false
output
- Finding hashicorp/local versions matching "2.5.0"...
- Installing hashicorp/local v2.5.0...

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file.

Review the .terraform.lock.hcl diff before you commit. For constraint semantics, see provider version constraints and lock file.

Situation Command
New provider added to configuration terraform init
Constraint tightened or relaxed on purpose terraform init -upgrade after reviewing the change
Fresh clone with committed lock file terraform init (reuses lock selections)

Case 3: Saved plan and lock file do not match

A saved plan is frozen at plan time. If dependency selections change afterward, terraform apply tfplan refuses to run.

bash
mkdir -p ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/saved-plan-mismatch
cd ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/saved-plan-mismatch

Apply a baseline, then save a plan:

bash
cat > versions.tf <<'EOF'
terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }
}
EOF

Seed a file resource so apply and plan have something to manage:

bash
cat > main.tf <<'EOF'
resource "local_file" "demo" {
  content  = "version one"
  filename = "${path.module}/demo.txt"
}
EOF

Create the baseline file on disk before saving a plan:

bash
terraform init -input=false
output
Terraform has been successfully initialized!

Apply the initial configuration:

bash
terraform apply -auto-approve -input=false

Change content and write a saved plan while the lock still matches:

bash
sed -i 's/version one/version two/' main.tf
terraform plan -out=tfplan -no-color

Alter provider dependency context before apply — pin local to = 2.5.0 and re-init:

bash
cat > versions.tf <<'EOF'
terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "= 2.5.0"
    }
  }
}
EOF

Re-init with -upgrade so the lock moves to v2.5.0:

bash
terraform init -upgrade -input=false

Apply the old plan file:

bash
terraform apply tfplan -no-color
output
Error: Inconsistent dependency lock file

The given plan file was created with a different set of external dependency
selections than the current configuration. A saved plan can be applied only
to the same configuration it was created from.

Create a new plan from the updated configuration.

Discard the stale plan and create a new one from the updated configuration and lock file:

bash
rm -f tfplan && terraform plan -out=tfplan -no-color

Treat saved plans as tied to a specific commit — configuration, .terraform.lock.hcl, and tfplan must travel together. The Terraform CI/CD lesson shows artifact handling for plan and apply jobs.


Case 4: CI plan and apply use different artifacts

Split pipelines fail when the apply job checks out a different commit, omits .terraform.lock.hcl, or runs terraform init -upgrade while the plan job did not.

Recommended artifact bundle for plan-then-apply:

  • Git commit SHA (same for both jobs)
  • Full configuration directory including .terraform.lock.hcl
  • Saved plan file (tfplan) from the plan job
  • Pinned terraform CLI version in both jobs

Apply job workflow:

  1. Check out the same commit the plan job used
  2. terraform init -input=false (no -upgrade unless the plan job also upgraded)
  3. terraform apply tfplan

If the plan job changed required_providers but did not commit an updated lock file, the apply job hits the same inconsistency error locally. Fix the lock in the plan stage, commit it, then regenerate the plan.


Should you delete .terraform.lock.hcl?

Deleting the lock file often makes the error disappear while hiding which dependency changed. That removes checksum pinning your team relies on and forces every init to resolve versions fresh.

Prefer updating the lock deliberately:

  • terraform init when you added providers
  • terraform init -upgrade when you changed constraints on purpose
  • git diff .terraform.lock.hcl before commit

Deliberate regeneration (delete lock, then init) is justified only when you intentionally reset provider pinning with team agreement — not as a first response to inconsistency errors.


Verify the fix

After reconciling dependencies, confirm providers, init, validate, and plan:

bash
cd ~/terraform-labs/terraform-inconsistent-dependency-lock-file/errors/config-mismatch-new-provider

List resolved provider selections:

bash
terraform providers
output
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/local] ~> 2.5
└── provider[registry.terraform.io/hashicorp/random] ~> 3.6

Re-run init, validate, and plan:

bash
terraform init -input=false

Init exits cleanly when the lock and plugins already match.

bash
terraform validate -no-color
output
Success! The configuration is valid.

Confirm plan succeeds with both providers resolved:

bash
terraform plan -no-color
output
Plan: 2 to add, 0 to change, 0 to destroy.

Compare .terraform.lock.hcl in version control — new provider blocks and version changes should match the configuration diff.

Destroy lab resources when finished:

bash
terraform destroy -auto-approve -input=false 2>/dev/null || true

Prevent inconsistent lock file errors

  • Commit .terraform.lock.hcl with root Terraform configurations kept in version control
  • Run terraform init after every required_providers edit before plan or apply
  • Use terraform init -upgrade only when you intend to change locked selections
  • Keep plan and apply jobs on the same commit, lock file, and Terraform version
  • Do not edit configuration between saving tfplan and running terraform apply tfplan

Diagnostic checklist

Error fragment Likely cause Fix
no version is selected New provider in config, not in lock terraform init
locked version selection … doesn't match Constraint changed without lock update terraform init -upgrade + review diff
plan file was created with a different set Saved plan stale after config or lock change New terraform plan -out=tfplan
Error on fresh clone Init not run terraform init
CI apply fails, local plan works Apply job missing lock file or different commit Align artifacts and init flags

References


Summary

Inconsistent dependency lock file means configuration, .terraform.lock.hcl, and sometimes a saved plan no longer agree on provider dependency selections. A newly added provider shows no version is selected until plain terraform init records it; a deliberate constraint change conflicts with the locked version until terraform init -upgrade re-resolves within the new range.

Saved plans embed the dependency context from plan time. After you change required_providers or the lock file, discard the old tfplan and create a new plan — terraform apply tfplan will refuse a mismatched bundle.

Commit the lock file for shared root configurations, run init after provider edits, and keep plan and apply CI jobs on the same commit and Terraform version. Deleting .terraform.lock.hcl masks the underlying drift; update the lock on purpose and review the diff instead.

For lock file mechanics and constraint syntax, continue with provider version constraints and lock file. For init flags and backend setup, see terraform init.


Frequently Asked Questions

1. What does Inconsistent dependency lock file mean in Terraform?

Your configuration's provider requirements do not match the provider selections recorded in .terraform.lock.hcl, or you are trying to apply a saved plan created with different dependency selections. Common cases include a newly added provider with no locked version, an updated provider constraint that conflicts with the locked selection, or a stale saved plan.

2. Should I run terraform init or terraform init -upgrade?

Run plain terraform init when you added a new provider and only need a lock entry for it. Run terraform init -upgrade when you deliberately changed version constraints and want Terraform to re-resolve selections within the new rules. Upgrade can move providers you did not intend to touch, so review the lock diff.

3. Can I apply a saved plan after changing required_providers?

No. A saved plan is valid only for the same configuration and dependency selections it was created with. After you change providers or constraints, run terraform init as needed and create a new plan with terraform plan -out=tfplan.

4. Should I delete .terraform.lock.hcl to fix this error?

Usually no. Deleting the lock file removes the team checksum record and masks which dependency changed. Run terraform init or init -upgrade to update the lock deliberately, then commit the diff. Delete and regenerate only when you intentionally reset provider pinning with team agreement.

5. Do I need to commit .terraform.lock.hcl in CI?

Yes for shared root configurations. Plan and apply jobs should check out the same commit, including the lock file, and run terraform init before plan or apply so provider selections match locally and in automation.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)