hashicorp/terraform · error
failed to read dependency lock file
Error message
failed to read dependency lock file: %s
What it means
Meta.ProviderFactories calls lockedDependencies() to read the dependency lock file (.terraform.lock.hcl). If that returns diagnostics with errors, the lock file could not be parsed or loaded, so provider factories cannot be constructed safely and the whole error is wrapped with this message. This is a hard gate: without a readable lock file Terraform refuses to build provider factories from locks.
Solutions
- Run terraform init -upgrade to regenerate a valid .terraform.lock.hcl from the current required_providers block.
- Inspect the embedded diagnostics (%s expands to diags.Err()) for the precise HCL parse location and fix that line.
- If the lock file has merge conflicts, resolve the conflict markers then re-run terraform init.
- As a last resort, back up and remove .terraform.lock.hcl, then terraform init to rebuild it; commit the regenerated file.
Example fix
# before: corrupt lock file causes 'failed to read dependency lock file' # after: regenerate rm .terraform.lock.hcl terraform init -upgrade git add .terraform.lock.hcl && git commit -m "chore: regenerate dependency lock file"
Defensive patterns
Strategy: validation
Validate before calling
// Validate the lock file parses before relying on ProviderFactories.
_, diags := m.lockedDependencies()
if diags.HasErrors() {
return fmt.Errorf("lock file unreadable, run 'terraform init -upgrade': %s", diags.Err())
} Prevention
- Commit .terraform.lock.hcl and resolve merge conflicts before running commands.
- Never hand-edit the lock file; always regenerate via terraform init/providers lock.
- Run terraform init in CI to regenerate a valid lock file when parse errors appear.
When it happens
Trigger: Meta.ProviderFactories() is invoked (transitively by most commands that need providers); m.lockedDependencies() returns diags where diags.HasErrors() is true, typically because the lock file is syntactically invalid, truncated, or missing required checksum/version blocks for a declared provider.
Common situations: Hand-edited or partially-merged .terraform.lock.hcl with HCL syntax errors; lock file corrupted by a git merge conflict left unresolved; lock file from an incompatible Terraform version; lock file deleted but referenced; non-UTF8 bytes written by a broken editor.
Related errors
- there is no package for
- Failed to convert provider version to Go version
- failed to verify checksum of
- Provider download blocked due to policy violations. Please…
- the cached package for
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/496dd90caee073fd.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/meta_providers.go:314
),
}
}
// ProviderFactories uses the selections made previously by an installer in
// the local cache directory (m.providerLocalCacheDir) to produce a map
// of provider addresses to factory functions to create instances of
// those providers.
//
// ProviderFactories will return an error if the installer's selections cannot
// be honored with what is currently in the cache, such as if a selected
// package has been removed from the cache or if the contents of a selected
// package have been modified outside of the installer. If it returns an error,
// the returned map may be incomplete or invalid, but will be as complete
// as possible given the cause of the error.
func (m *Meta) ProviderFactories() (map[addrs.Provider]providers.Factory, error) {
locks, diags := m.lockedDependencies()
if diags.HasErrors() {
return nil, fmt.Errorf("failed to read dependency lock file: %s", diags.Err())
}
return m.providerFactoriesFromLocks(locks)
}
// ProviderFactoriesFromLocks receives in memory locks and uses them to produce a map
// of provider addresses to factory functions to create instances of
// those providers.
//
// ProviderFactoriesFromLocks should only be used if the calling code relies on locks
// that have not yet been persisted to a dependency lock file on disk. Realistically, this
// means only code in the init command should use this method.
func (m *Meta) ProviderFactoriesFromLocks(configLocks *depsfile.Locks) (map[addrs.Provider]providers.Factory, error) {
// Ensure overrides and unmanaged providers are reflected in the returned list of factories,
// while avoiding mutating the in-memory
locks := m.annotateDependencyLocksWithOverrides(configLocks.DeepCopy())
return m.providerFactoriesFromLocks(locks)View on GitHub (pinned to d32a084675)