{"record":{"id":"e8e5c32a1b25341e","repo":"hashicorp/nomad","slug":"duplicate-default-identities-found","errorCode":null,"errorMessage":"Duplicate default identities found","messagePattern":"Duplicate default identities found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":8436,"sourceCode":"\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\\\"%s\\\" MountDir=\\\"%s\\\"\", t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir))\n\t\t}\n\n\t\t// TODO: Investigate validation of the PluginMountDir. Not much we can do apart from check IsAbs until after we understand its execution environment though :(\n\t}\n\n\t// Validate default Identity\n\tif t.Identity != nil {\n\t\tif err := t.Identity.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Identity %q is invalid: %w\", t.Identity.Name, err))\n\t\t}\n\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}","sourceCodeStart":8418,"sourceCodeEnd":8454,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L8418-L8454","documentation":"Task.Canonicalize is supposed to move the default workload identity (name \"default\") out of the Identities slice; if Task.Validate still sees an identity named WorkloadIdentityDefaultName inside t.Identities, it reports 'Duplicate default identities found'. It means both an implicit/default identity and an explicit identities entry named 'default' exist.","triggerScenarios":"A task that defines identity { } AND lists an identity named \"default\" in its identities list; submitting a pre-canonicalized Task struct via the API where canonicalization didn't run or the duplicate was added after.","commonSituations":"Hand-built JSON job payloads sent to the Nomad API that include identities: [{\"name\":\"default\"}] alongside identity block; tooling that merges identity blocks; jobspecs migrated between versions duplicating the default.","solutions":["Remove the identities entry named \"default\" and configure the top-level identity block instead","Rename the extra entry if a distinct identity is intended (it must not be called \"default\")","If building Tasks programmatically, call Canonicalize() before Validate/submit"],"exampleFix":"// before\nidentity {\n  env = true\n}\nidentities = [{ name = \"default\", aud = [\"foo\"] }]\n// after\nidentity {\n  env = true\n  aud = [\"foo\"]\n}","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, wid := range t.Identities {\n    if wid.Name == \"default\" {\n        return errors.New(\"do not list an identity named \\\"default\\\"; use the identity block\")\n    }\n    if seen[wid.Name] { return fmt.Errorf(\"duplicate identity %q\", wid.Name) }\n    seen[wid.Name] = true\n}","typeGuard":"func hasDefaultIdentity(ids []*structs.WorkloadIdentity) bool {\n    for _, w := range ids { if w.Name == \"default\" { return true } }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Never add identities entries named \"default\"; configure identity { } instead","Call Task.Canonicalize() before submitting programmatically built jobs","Lint job templates to prevent generators from emitting a default identity in identities"],"tags":["nomad","workload-identity","validation","duplicate"],"backgroundTag":"duplicate-identity","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"}