{"record":{"id":"695eec69f6cac29c","repo":"hashicorp/nomad","slug":"duplicate-secret-q-found","errorCode":null,"errorMessage":"Duplicate secret %q found","messagePattern":"Duplicate secret %q found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":8447,"sourceCode":"\t}\n\n\t// Validate Identities\n\tfor _, wid := range t.Identities {\n\t\t// Task.Canonicalize should move the default identity out of the Identities\n\t\t// slice, so if one is found that means it is a duplicate.\n\t\tif wid.Name == WorkloadIdentityDefaultName {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Duplicate default identities found\"))\n\t\t}\n\n\t\tif err := wid.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Identity %q is invalid: %w\", wid.Name, err))\n\t\t}\n\t}\n\n\tsecrets := make(map[string]bool)\n\tfor _, s := range t.Secrets {\n\t\tif _, ok := secrets[s.Name]; ok {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Duplicate secret %q found\", s.Name))\n\t\t} else {\n\t\t\tsecrets[s.Name] = true\n\t\t}\n\n\t\tif s.Provider == SecretProviderVault && t.Vault == nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Secret %q has provider \\\"vault\\\" but no vault block\", s.Name))\n\t\t}\n\n\t\tif err := s.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Secret %q is invalid: %w\", s.Name, err))\n\t\t}\n\t}\n\n\treturn mErr.ErrorOrNil()\n}\n\n// validateServices takes a task and validates the services within it are valid\n// and reference ports that exist.","sourceCodeStart":8429,"sourceCodeEnd":8465,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L8429-L8465","documentation":"Task.Validate tracks task secret names in a map; if two secret blocks share the same name, the second occurrence logs 'Duplicate secret %q found'. Names must be unique because they become distinct env/file keys for the task's secrets.","triggerScenarios":"A task with two secrets { } blocks using the same name = \"db_password\", or an API-submitted Task whose Secrets slice contains repeated names.","commonSituations":"Copy-pasted secret blocks where only provider/env was changed but name left identical; templated job generation that appends secrets without uniquifying names; merging job fragments that each define the same secret name.","solutions":["Rename one of the duplicate secret blocks to a unique name","Delete the redundant block if both point at the same source","Fix the generator/template that emits secret names so each is unique"],"exampleFix":"// before\nsecrets {\n  name   = \"db_password\"\n  provider = \"vault\"\n  path   = \"kv/db\"\n}\nsecrets {\n  name   = \"db_password\"\n  provider = \"vault\"\n  path   = \"kv/db2\"\n}\n// after\nsecrets {\n  name   = \"db_password\"\n  provider = \"vault\"\n  path   = \"kv/db\"\n}\nsecrets {\n  name   = \"db_password_v2\"\n  provider = \"vault\"\n  path   = \"kv/db2\"\n}","handlingStrategy":"validation","validationCode":"names := map[string]bool{}\nfor _, s := range t.Secrets {\n    if names[s.Name] { return fmt.Errorf(\"duplicate secret %q\", s.Name) }\n    names[s.Name] = true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give each secret block a unique, descriptive name","Review generated jobspecs for duplicated names after templating","Add a pre-submit linter that asserts uniqueness of secret names"],"tags":["nomad","secrets","validation","duplicate"],"backgroundTag":"duplicate-resource-name","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}