{"record":{"id":"74f6a1585fe40749","repo":"hashicorp/nomad","slug":"task-d-redefines-s-from-task-d","errorCode":null,"errorMessage":"Task %d redefines '%s' from task %d","messagePattern":"Task (.+?) redefines '(.+?)' from task (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":7256,"sourceCode":"\t\t\tif err := tg.Migrate.Validate(); err != nil {\n\t\t\t\tmErr = multierror.Append(mErr, err)\n\t\t\t}\n\t\t}\n\tdefault:\n\t\tif tg.Migrate != nil {\n\t\t\tmErr = multierror.Append(mErr, fmt.Errorf(\"Job type %q does not allow migrate block\", j.Type))\n\t\t}\n\t}\n\n\t// Check that there is only one leader task if any\n\ttasks := make(map[string]int)\n\tleaderTasks := 0\n\tmainTasks := 0\n\tfor idx, task := range tg.Tasks {\n\t\tif task.Name == \"\" {\n\t\t\tmErr = multierror.Append(mErr, fmt.Errorf(\"Task %d missing name\", idx+1))\n\t\t} else if existing, ok := tasks[task.Name]; ok {\n\t\t\tmErr = multierror.Append(mErr, fmt.Errorf(\"Task %d redefines '%s' from task %d\", idx+1, task.Name, existing+1))\n\t\t} else {\n\t\t\ttasks[task.Name] = idx\n\t\t}\n\n\t\tif task.Leader {\n\t\t\tleaderTasks++\n\t\t}\n\n\t\tif task.IsMain() {\n\t\t\tmainTasks++\n\t\t}\n\t}\n\n\tif leaderTasks > 1 {\n\t\tmErr = multierror.Append(mErr, fmt.Errorf(\"Only one task may be marked as leader\"))\n\t}\n\n\t// A task group made up entirely of lifecycle tasks (prestart, poststart, or","sourceCodeStart":7238,"sourceCodeEnd":7274,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L7238-L7274","documentation":"TaskGroup.Validate builds a map of task names and rejects duplicates: when a task reuses a name already defined earlier in the same group, this error is appended, referencing the 1-indexed positions of both the duplicate and the original task. Task names must be unique within a task group because they key allocation state, service checks, and log streams.","triggerScenarios":"Submitting a job with two `task` blocks sharing the same `name` inside one `group` block.","commonSituations":"Copy-pasting a task block and forgetting to rename it; merging job fragments; templated loops generating tasks with identical names.","solutions":["Rename one of the duplicate task blocks to a unique name within the group.","If the tasks are meant to be independent instances, place them in separate groups instead."],"exampleFix":"// before\ntask \"app\" { driver = \"docker\" }\ntask \"app\" { driver = \"exec\" }\n// after\ntask \"app\" { driver = \"docker\" }\ntask \"app-sidecar\" { driver = \"exec\" }","handlingStrategy":"validation","validationCode":"// Go: enforce unique task names per group\nfor _, tg := range job.TaskGroups {\n  seen := map[string]bool{}\n  for _, t := range tg.Tasks {\n    if seen[t.Name] {\n      return fmt.Errorf(\"group %q: duplicate task name %q\", tg.Name, t.Name)\n    }\n    seen[t.Name] = true\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Name tasks after copying a block and immediately rename it.","In generators, derive task names from unique loop keys.","Add a unit test that validates all canonical job specs with Nomad's structs API."],"tags":["nomad","job-validation","duplicate-name"],"backgroundTag":"nomad-job-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"}