{"record":{"id":"1e27fb59f7f4982a","repo":"hashicorp/nomad","slug":"job-task-group-d-missing-name","errorCode":null,"errorMessage":"Job task group %d missing name","messagePattern":"Job task group (.+?) missing name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":4828,"sourceCode":"\n\tconst MaxDescriptionCharacters = 1000\n\tif j.UI != nil {\n\t\tif len(j.UI.Description) > MaxDescriptionCharacters {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"UI description must be under 1000 characters, currently %d\", len(j.UI.Description)))\n\t\t}\n\t}\n\n\tif j.VersionTag != nil {\n\t\tif len(j.VersionTag.Description) > MaxDescriptionCharacters {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Tagged version description must be under 1000 characters, currently %d\", len(j.VersionTag.Description)))\n\t\t}\n\t}\n\n\t// Check for duplicate task groups\n\ttaskGroups := make(map[string]int)\n\tfor idx, tg := range j.TaskGroups {\n\t\tif tg.Name == \"\" {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Job task group %d missing name\", idx+1))\n\t\t} else if existing, ok := taskGroups[tg.Name]; ok {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Job task group %d redefines '%s' from group %d\", idx+1, tg.Name, existing+1))\n\t\t} else {\n\t\t\ttaskGroups[tg.Name] = idx\n\t\t}\n\n\t\tif tg.ShutdownDelay != nil && *tg.ShutdownDelay < 0 {\n\t\t\tmErr.Errors = append(mErr.Errors, errors.New(\"ShutdownDelay must be a positive value\"))\n\t\t}\n\n\t\tif j.Type == \"system\" && tg.Count > 1 {\n\t\t\tmErr.Errors = append(mErr.Errors,\n\t\t\t\tfmt.Errorf(\"Job task group %s has count %d. Count cannot exceed 1 with system scheduler\",\n\t\t\t\t\ttg.Name, tg.Count))\n\t\t}\n\t}\n\n\t// Validate the task group","sourceCodeStart":4810,"sourceCodeEnd":4846,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L4810-L4846","documentation":"Job.Validate() checks every task group has a non-empty Name, appending 'Job task group %d missing name' (1-based index) when tg.Name is empty. Group names are required keys for allocation tracking and the API.","triggerScenarios":"Submitting a job JSON/HCL where a group block omits the name, e.g. JSON produced by a script that drops the Name field or an HCL group without a label.","commonSituations":"Programmatic job generation (SDK/API) where TaskGroups structs are built without setting Name, or malformed HCL where the group label was accidentally removed.","solutions":["Add a name to the group block or set TaskGroups[i].Name in the JSON","Ensure generated job specs always populate group names","Run 'nomad job validate' on generated specs in CI","If parsing HCL, verify the group label survived templating"],"exampleFix":"// before\ngroup {\n  count = 1\n}\n// after\ngroup \"web\" {\n  count = 1\n}","handlingStrategy":"validation","validationCode":"for i, tg := range job.TaskGroups {\n    if tg.Name == \"\" {\n        return fmt.Errorf(\"task group %d missing name\", i+1)\n    }\n}\nreturn nil","typeGuard":"func hasNamedGroups(j *structs.Job) bool {\n    for _, tg := range j.TaskGroups {\n        if tg == nil || tg.Name == \"\" {\n            return false\n        }\n    }\n    return len(j.TaskGroups) > 0\n}","tryCatchPattern":"if err := job.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"missing name\") {\n        return ErrGroupMissingName\n    }\n    return err\n}","preventionTips":["Always label group blocks in HCL","When building jobs via Go API, set TaskGroups[i].Name explicitly","Validate generated JSON specs in CI"],"tags":["nomad","job-validation","task-group","missing-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"}