hashicorp/terraform · critical
expected exactly one provider requirement for the destinatio
Error message
expected exactly one provider requirement for the destination state store provider %q, got %d
What it means
This panic fires at the end of getDestinationStateStoreProviderRequirements when the filtered requirements map does not contain exactly one entry. The function expects precisely one provider requirement matching the destination state_store provider; zero means no matching required_providers entry was found, two+ means duplicate entries for the same provider address.
Source
Thrown at internal/command/state_migrate.go:477
for _, providerReq := range configReqs.RequiredProviders {
if providerReq.Type.Equals(provider) {
con, err := providerreqs.ParseVersionConstraints(providerReq.Requirement.Required.String())
if err != nil {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid version constraint syntax for state store provider",
// The errors returned by ParseVersionConstraint already include
// the section of input that was incorrect, so we don't need to
// include that here.
Detail: fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
Subject: providerReq.Requirement.DeclRange.Ptr(),
})
}
req[providerReq.Type] = con
}
}
if len(req) != 1 {
panic(fmt.Sprintf("expected exactly one provider requirement for the destination state store provider %q, got %d", provider, len(req)))
}
return req, diags
}
// saveDependencyLockFile overwrites the contents of the dependency lock file.
func (c *StateMigrateCommand) saveDependencyLockFile(previousLocks, newLocks *depsfile.Locks, view views.ProviderLockingLogger) (output bool, diags tfdiags.Diagnostics) {
// The state migrate command does not support the -lockfile=readonly flag
// This flag is specific to the init command, and can only take "" or "readonly" as values.
// As state migrate doesn't take this flag, we can safely set it to "" here.
flagLockfile := ""
return c.Meta.saveDependencyLockFile(previousLocks, newLocks, c.incompleteProviders, flagLockfile, view)
}
// getSingleProvider is used to download the source and/or destination state store providers during a state migration.
// Download of the up to 2 providers is kept separate due to:
// - Potential for downloading different versions of the same providerView on GitHub (pinned to d32a084675)
Solutions
- Verify the `provider = "..."` value in the state_store block exactly matches the `source = "..."` in required_providers (full registry namespace + type).
- Remove any duplicate required_providers entries for the same provider source; consolidate to one declaration with one version constraint.
- Run `terraform init` to confirm Terraform resolves exactly one requirement for the state-store provider.
Example fix
// before — duplicate required_providers for the same source
required_providers {
a = { source = "registry.terraform.io/hashicorp/tfstate-mysql", version = ">= 0.1" }
b = { source = "registry.terraform.io/hashicorp/tfstate-mysql", version = ">= 0.2" }
}
// after — single canonical declaration
required_providers {
tfstate-mysql = {
source = "registry.terraform.io/hashicorp/tfstate-mysql"
version = ">= 0.2"
}
} Defensive patterns
Strategy: validation
Validate before calling
// Caller-side guard: confirm exactly one matching requirement exists.
matches := 0
for _, pr := range configReqs.RequiredProviders {
if pr.Type.Equals(provider) { matches++ }
}
if matches != 1 {
return fmt.Errorf("need exactly one required_providers entry for %q, found %d", provider, matches)
} Type guard
// n/a
Prevention
- Use exactly one required_providers local name per provider source address.
- Cross-check the state_store `provider` attribute character-for-character against required_providers `source`.
- Add a config lint rule forbidding duplicate required_providers sources.
When it happens
Trigger: State migration setup: after iterating configReqs.RequiredProviders and keeping only entries whose Type equals the destination provider, len(req) != 1. Zero matches = the required_providers block names a different provider than the state_store block; >1 = the same provider source is declared twice (e.g. two required_providers entries with the same source but different local names).
Common situations: A config with a state_store block pointing at provider A but a required_providers entry only for provider B (mismatch). Or a copy-paste required_providers block declaring the same source twice under different local names.
Related errors
- expected one provider requirement for the destination state
- expected exactly one provider requirement for the destinatio
- failed to encode main index: %s
- failed to encode version index: %s
- backendDiags.Err()
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/89ba84309b8da00d.
Report an issue: GitHub.