{"record":{"id":"86c0e4560c0bfee5","repo":"hashicorp/terraform","slug":"no-more-than-one-credentials-helper-block-may-be-s","errorCode":null,"errorMessage":"No more than one credentials_helper block may be specified","messagePattern":"No more than one credentials_helper block may be specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/cliconfig/cliconfig.go","lineNumber":316,"sourceCode":"\t\t\t\tfmt.Errorf(\"The host %q block has an invalid hostname: %s\", givenHost, err),\n\t\t\t)\n\t\t}\n\t}\n\n\t// Check that all \"credentials\" blocks have valid hostnames.\n\tfor givenHost := range c.Credentials {\n\t\t_, err := svchost.ForComparison(givenHost)\n\t\tif err != nil {\n\t\t\tdiags = diags.Append(\n\t\t\t\tfmt.Errorf(\"The credentials %q block has an invalid hostname: %s\", givenHost, err),\n\t\t\t)\n\t\t}\n\t}\n\n\t// Should have zero or one \"credentials_helper\" blocks\n\tif len(c.CredentialsHelpers) > 1 {\n\t\tdiags = diags.Append(\n\t\t\tfmt.Errorf(\"No more than one credentials_helper block may be specified\"),\n\t\t)\n\t}\n\n\t// Should have zero or one \"provider_installation\" blocks\n\tif len(c.ProviderInstallation) > 1 {\n\t\tdiags = diags.Append(\n\t\t\tfmt.Errorf(\"No more than one provider_installation block may be specified\"),\n\t\t)\n\t}\n\n\tif c.PluginCacheDir != \"\" {\n\t\t_, err := os.Stat(c.PluginCacheDir)\n\t\tif err != nil {\n\t\t\tdiags = diags.Append(\n\t\t\t\tfmt.Errorf(\"The specified plugin cache dir %s cannot be opened: %s\", c.PluginCacheDir, err),\n\t\t\t)\n\t\t}\n\t}","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/cliconfig/cliconfig.go#L298-L334","documentation":"Thrown when the CLI configuration contains more than one credentials_helper block. Terraform allows at most one credentials_helper to avoid ambiguity about which plugin handles credential storage and retrieval. The check runs during config validation after all config files are parsed and merged.","triggerScenarios":"len(c.CredentialsHelpers) > 1 after parsing and merging all config file(s). This happens when multiple credentials_helper blocks appear in the same file or across merged config files (e.g., user config plus TF_CLI_CONFIG_FILE).","commonSituations":"Copy-pasting a credentials_helper block creating duplicates; merging multiple config files each defining their own credentials_helper; config file from a different setup pasted without removing the existing block.","solutions":["Remove all but one credentials_helper block from your .terraformrc","If using config file merging, ensure only one file defines credentials_helper","Review the full config including any file pointed to by TF_CLI_CONFIG_FILE"],"exampleFix":"// before\ndev_overrides {}\ncredentials_helper \"foo\" { args = [] }\ncredentials_helper \"bar\" { args = [] }\n\n// after\ncredentials_helper \"foo\" { args = [] }","handlingStrategy":"validation","validationCode":"// Count credentials_helper blocks in config before deployment\nfunc countCredentialsHelpers(path string) (int, error) {\n    src, err := os.ReadFile(path)\n    if err != nil {\n        return 0, err\n    }\n    return strings.Count(string(src), \"credentials_helper\"), nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Define at most one credentials_helper block across all config files","Audit merged config files for duplicate blocks","Use a single source of truth for CLI configuration","Run a config lint step in CI that checks for duplicate top-level blocks"],"tags":["cli-config","credentials-helper","validation","duplicate"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}