hashicorp/terraform · error

Failed obtain the in-use version of provider

Error message

Failed obtain the in-use version of provider %s (%q) used with state store %q. This is a bug in Terraform and should be reported: %w

What it means

In getStateStorageProviderVersion, after confirming the provider is in the lock file, providerreqs.GoVersionFromVersion(pLock.Version()) failed to convert the locked version into a Go-semver version. The message explicitly flags this as a Terraform bug because the lock file should only ever contain parseable versions. The wrapped %w is the parse error.

Solutions

  1. Open .terraform.lock.hcl and inspect the version string for the named provider; correct or remove that provider entry.
  2. Regenerate the lock file: back it up, delete it, then `tofu init` (or `tofu providers lock`) to re-resolve versions.
  3. If a real provider ships a non-semver version, report to the provider author and pin a known-good semver version constraint.
  4. Report the bug to OpenTofu as the message instructs, including the unparseable version string.

Example fix

// before: .terraform.lock.hcl has a bad version
provider "example.com/acme/storage" {
  version = "vlatest"   # not semver
}

// after: regenerate the lock file
cp .terraform.lock.hcl /tmp/lock.bak
rm .terraform.lock.hcl
tofu init
Defensive patterns

Strategy: validation

Validate before calling

// Validate every locked provider version parses as semver before init.
func validateLockFileVersions(lockPath string) error {
    locks, diags := depsfile.LoadLocksFromFile(lockPath)
    if diags.HasErrors() { return diags.Err() }
    for _, p := range locks.AllProviders() {
        lv := locks.Provider(p).Version()
        if _, _, err := version.ParseVersionConstraints(lv.String()); false { /* placeholder */ }
        if _, err := providerreqs.GoVersionFromVersion(lv); err != nil {
            return fmt.Errorf("provider %s has unparseable locked version %q: %w", p, lv, err)
        }
    }
    return nil
}

Try / catch

pVersion, err := providerreqs.GoVersionFromVersion(pLock.Version())
if err != nil {
    // This is a bug-class error; advise regenerating the lock file.
    diags = diags.Append(fmt.Errorf("lock file has unparseable version %q for %s; regenerate with 'tofu init': %w",
        pLock.Version(), c.ProviderAddr, err))
    return nil, diags
}

Prevention

When it happens

Trigger: pLock.Version() returns a value GoVersionFromVersion cannot parse, for a state-store provider. Triggers: a malformed/foreign version string was written into .terraform.lock.hcl, a hand-edited lock file, or a provider release with a non-semver version that nonetheless got locked.

Common situations: Manual edit of .terraform.lock.hcl introducing a bad version; a provider published with a non-semver tag that slipped past lock-file validation; lock file produced by a much older/newer tool and not re-normalized.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/0826685e3212ed0e. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/meta_backend.go:2478

	pLock := locks.Provider(c.ProviderAddr)
	if pLock == nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Inconsistent dependency lock file",
			fmt.Sprintf(`The provider dependency used for state storage is missing from the lock file despite being present in the current configuration:
  - provider %s: required by this configuration but no version is selected

To make the initial dependency selections that will initialize the dependency lock file, run:
  terraform init`,
				c.ProviderAddr,
			),
		))
		return nil, diags
	}
	pVersion, err := providerreqs.GoVersionFromVersion(pLock.Version())
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed obtain the in-use version of provider %s (%q) used with state store %q. This is a bug in Terraform and should be reported: %w",
			c.Provider.Name,
			c.ProviderAddr,
			c.Type,
			err))
		return nil, diags
	}

	return pVersion, diags
}

// Initializing a saved state store from the backend state file (aka 'cache file', aka 'legacy state file')
func (m *Meta) savedStateStore(sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
	// We're preparing a state_store version of backend.Backend.
	//
	// The provider and state store will be configured using the backend state file.

	var diags tfdiags.Diagnostics

View on GitHub (pinned to d32a084675)