{"record":{"id":"d5087770eb520523","repo":"hashicorp/nomad","slug":"template-d-has-same-destination-as-d","errorCode":null,"errorMessage":"Template %d has same destination as %d","messagePattern":"Template (.+?) has same destination as (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":8340,"sourceCode":"\t}\n\n\t// Validate Vault.\n\tif t.Vault != nil {\n\t\tif err := t.Vault.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Vault validation failed: %v\", err))\n\t\t}\n\t}\n\n\t// Validate templates.\n\tdestinations := make(map[string]int, len(t.Templates))\n\tfor idx, tmpl := range t.Templates {\n\t\tif err := tmpl.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Template %d validation failed: %s\", idx+1, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\n\t\tif other, ok := destinations[tmpl.DestPath]; ok {\n\t\t\touter := fmt.Errorf(\"Template %d has same destination as %d\", idx+1, other)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t} else {\n\t\t\tdestinations[tmpl.DestPath] = idx + 1\n\t\t}\n\t}\n\n\t// Validate actions.\n\tactions := make(map[string]bool)\n\tfor _, action := range t.Actions {\n\t\tif err := action.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Action %s validation failed: %s\", action.Name, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\n\t\tif handled, seen := actions[action.Name]; seen && !handled {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Action %s defined multiple times\", action.Name))\n\t\t\tactions[action.Name] = true\n\t\t\tcontinue","sourceCodeStart":8322,"sourceCodeEnd":8358,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L8322-L8358","documentation":"Task.Validate detects two template blocks in the same task whose destination paths collide and reports \"Template %d has same destination as %d\" (1-based indices). Two templates rendering to the same file would nondeterministically overwrite each other, so it is rejected at job validation time.","triggerScenarios":"A task defines two or more template stanzas with the identical `destination` path (including the same relative path via `local/`).","commonSituations":"Copy-pasting a template stanza and forgetting to change destination; rendering similar configs to the same file; generated HCL where destinations are parameterized and collide.","solutions":["Give each template a unique destination path (e.g. local/a.conf vs local/b.conf)","If one file needs content from multiple sources, merge into a single template block","Run `nomad job validate` to enumerate all duplicate destinations before submit"],"exampleFix":"// before\ntemplate {\n  data        = \"A=1\"\n  destination = \"local/env.txt\"\n}\ntemplate {\n  data        = \"B=2\"\n  destination = \"local/env.txt\"\n}\n// after\ntemplate {\n  data        = \"A=1\"\n  destination = \"local/a.env\"\n}\ntemplate {\n  data        = \"B=2\"\n  destination = \"local/b.env\"\n}","handlingStrategy":"validation","validationCode":"seen := map[string]int{}\nfor i, tmpl := range task.Templates {\n    if j, ok := seen[tmpl.DestPath]; ok {\n        return fmt.Errorf(\"templates %d and %d share destination %q\", j, i+1, tmpl.DestPath)\n    }\n    seen[tmpl.DestPath] = i + 1\n}","typeGuard":null,"tryCatchPattern":"if err := job.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"has same destination\") { /* dedupe templates */ }\n}","preventionTips":["Generate destinations from unique names, never copy-paste literals","Lint job files for duplicate destination strings","Keep one template per config file"],"tags":["nomad","job-validation","template","duplicate"],"backgroundTag":"job-spec-validation-failed","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"}