{"record":{"id":"89ba84309b8da00d","repo":"hashicorp/terraform","slug":"expected-exactly-one-provider-requirement-for-the","errorCode":null,"errorMessage":"expected exactly one provider requirement for the destination state store provider %q, got %d","messagePattern":"expected exactly one provider requirement for the destination state store provider %q, got (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/command/state_migrate.go","lineNumber":477,"sourceCode":"\tfor _, providerReq := range configReqs.RequiredProviders {\n\t\tif providerReq.Type.Equals(provider) {\n\t\t\tcon, err := providerreqs.ParseVersionConstraints(providerReq.Requirement.Required.String())\n\t\t\tif err != nil {\n\t\t\t\tdiags = diags.Append(&hcl.Diagnostic{\n\t\t\t\t\tSeverity: hcl.DiagError,\n\t\t\t\t\tSummary:  \"Invalid version constraint syntax for state store provider\",\n\t\t\t\t\t// The errors returned by ParseVersionConstraint already include\n\t\t\t\t\t// the section of input that was incorrect, so we don't need to\n\t\t\t\t\t// include that here.\n\t\t\t\t\tDetail:  fmt.Sprintf(\"Incorrect version constraint syntax: %s.\", err.Error()),\n\t\t\t\t\tSubject: providerReq.Requirement.DeclRange.Ptr(),\n\t\t\t\t})\n\t\t\t}\n\t\t\treq[providerReq.Type] = con\n\t\t}\n\t}\n\tif len(req) != 1 {\n\t\tpanic(fmt.Sprintf(\"expected exactly one provider requirement for the destination state store provider %q, got %d\", provider, len(req)))\n\t}\n\n\treturn req, diags\n}\n\n// saveDependencyLockFile overwrites the contents of the dependency lock file.\nfunc (c *StateMigrateCommand) saveDependencyLockFile(previousLocks, newLocks *depsfile.Locks, view views.ProviderLockingLogger) (output bool, diags tfdiags.Diagnostics) {\n\t// The state migrate command does not support the -lockfile=readonly flag\n\t// This flag is specific to the init command, and can only take \"\" or \"readonly\" as values.\n\t// As state migrate doesn't take this flag, we can safely set it to \"\" here.\n\tflagLockfile := \"\"\n\n\treturn c.Meta.saveDependencyLockFile(previousLocks, newLocks, c.incompleteProviders, flagLockfile, view)\n}\n\n// getSingleProvider is used to download the source and/or destination state store providers during a state migration.\n// Download of the up to 2 providers is kept separate due to:\n// - Potential for downloading different versions of the same provider","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/state_migrate.go#L459-L495","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before — duplicate required_providers for the same source\nrequired_providers {\n  a = { source = \"registry.terraform.io/hashicorp/tfstate-mysql\", version = \">= 0.1\" }\n  b = { source = \"registry.terraform.io/hashicorp/tfstate-mysql\", version = \">= 0.2\" }\n}\n// after — single canonical declaration\nrequired_providers {\n  tfstate-mysql = {\n    source  = \"registry.terraform.io/hashicorp/tfstate-mysql\"\n    version = \">= 0.2\"\n  }\n}","handlingStrategy":"validation","validationCode":"// Caller-side guard: confirm exactly one matching requirement exists.\nmatches := 0\nfor _, pr := range configReqs.RequiredProviders {\n  if pr.Type.Equals(provider) { matches++ }\n}\nif matches != 1 {\n  return fmt.Errorf(\"need exactly one required_providers entry for %q, found %d\", provider, matches)\n}","typeGuard":"// n/a","tryCatchPattern":null,"preventionTips":["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."],"tags":["terraform-cli","state-store","state-migrate","panic","invariant","required-providers"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}