{"record":{"id":"703cb17624be6923","repo":"hashicorp/nomad","slug":"missing-job-task-groups","errorCode":null,"errorMessage":"Missing job task groups","messagePattern":"Missing job task groups","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":4777,"sourceCode":"\tswitch j.Type {\n\tcase JobTypeCore, JobTypeService, JobTypeBatch, JobTypeSystem, JobTypeSysBatch:\n\tcase \"\":\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job type\"))\n\tdefault:\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Invalid job type: %q\", j.Type))\n\t}\n\tif len(j.Datacenters) == 0 && !j.IsMultiregion() {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job datacenters\"))\n\t} else {\n\t\tfor _, v := range j.Datacenters {\n\t\t\tif v == \"\" {\n\t\t\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Job datacenter must be non-empty string\"))\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(j.TaskGroups) == 0 {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job task groups\"))\n\t}\n\tfor idx, constr := range j.Constraints {\n\t\tif err := constr.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Constraint %d validation failed: %s\", idx+1, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\t}\n\tif j.Type == JobTypeSystem {\n\t\tif j.Affinities != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"System jobs may not have an affinity block\"))\n\t\t}\n\t} else {\n\t\tfor idx, affinity := range j.Affinities {\n\t\t\tif err := affinity.Validate(); err != nil {\n\t\t\t\touter := fmt.Errorf(\"Affinity %d validation failed: %s\", idx+1, err)\n\t\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t\t}\n\t\t}","sourceCodeStart":4759,"sourceCodeEnd":4795,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L4759-L4795","documentation":"Job.Validate() requires at least one task group. A Nomad job is a container of task groups; with none defined there is nothing to schedule, so the spec is invalid and this error is appended to the multierror.","triggerScenarios":"Submitting a job spec with no `group` blocks via nomad job run or POST /v1/jobs, or calling Job.Validate() on a structs.Job with len(j.TaskGroups) == 0.","commonSituations":"Deleting all groups while refactoring an HCL file; template conditionals that render zero group blocks; programmatic job builders that never append a TaskGroup.","solutions":["Add at least one `group \"name\" { ... }` block containing a `task` stanza to the job file","Ensure template logic always renders at least one group","Append at least one &TaskGroup{...} (with a task) when building jobs in Go"],"exampleFix":"// before\njob \"web-app\" {\n  type = \"service\"\n  datacenters = [\"dc1\"]\n}\n// after\njob \"web-app\" {\n  type = \"service\"\n  datacenters = [\"dc1\"]\n  group \"web\" {\n    task \"server\" {\n      driver = \"docker\"\n      config { image = \"nginx\" }\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"if len(j.TaskGroups) == 0 {\n    return fmt.Errorf(\"job must define at least one task group\")\n}","typeGuard":"func hasTaskGroups(j *structs.Job) bool { return j != nil && len(j.TaskGroups) > 0 }","tryCatchPattern":"if err := job.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"Missing job task groups\") {\n        return fmt.Errorf(\"add at least one group block with a task: %w\", err)\n    }\n}","preventionTips":["Never delete all group blocks when refactoring job files","Ensure template conditionals always render at least one group","Start from `nomad init` templates and run nomad job validate in CI"],"tags":["nomad","go","validation","job-spec"],"backgroundTag":"missing-required-argument","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"}