{"record":{"id":"b26982e84ab9c7ac","repo":"hashicorp/nomad","slug":"task-group-s-validation-failed-v","errorCode":null,"errorMessage":"Task group %s validation failed: %v","messagePattern":"Task group (.+?) validation failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":4849,"sourceCode":"\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\n\tfor _, tg := range j.TaskGroups {\n\t\tif err := tg.Validate(j); err != nil {\n\t\t\touter := fmt.Errorf(\"Task group %s validation failed: %v\", tg.Name, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\t}\n\n\t// Validate periodic is only used with batch or sysbatch jobs.\n\tif j.IsPeriodic() && j.Periodic.Enabled {\n\t\tif j.Type != JobTypeBatch && j.Type != JobTypeSysBatch {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\n\t\t\t\t\"Periodic can only be used with %q or %q scheduler\", JobTypeBatch, JobTypeSysBatch,\n\t\t\t))\n\t\t}\n\n\t\tif err := j.Periodic.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t}\n\t}\n\n\tif j.IsParameterized() {","sourceCodeStart":4831,"sourceCodeEnd":4867,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L4831-L4867","documentation":"This error is produced by Job.Validate in nomad/structs/structs.go when one of a job's task groups fails its own TaskGroup.Validate check. Nomad wraps the group-level validation error in a 'Task group %s validation failed: %v' message and appends it to a multi-error, so the inner %v carries the actual rule that was violated (e.g. missing task, bad count, invalid update block).","triggerScenarios":"Submitting or validating a job spec (via `nomad job run`, `nomad job validate`, API /v1/jobs, or CLI commands like job allocs that validate) where at least one TaskGroups[] entry fails Validate — e.g. a group with no tasks, negative count, overlapping ports, or invalid restart/update stanza.","commonSituations":"Hand-edited HCL/JSON job files; templates generating job specs; CI pipelines submitting jobs without running `nomad job validate` first; API clients constructing structs.Job structs directly and omitting required group fields.","solutions":["Read the inner %v text after the colon — it names the actual group-level rule that failed.","Run `nomad job validate <file>` locally to get the full multi-error list before submitting.","Fix the offending stanza in the named task group (count, tasks, network, update, etc.).","If the spec is generated, add a pre-submit validation step using the same structs.Job.Validate path."],"exampleFix":"// before\njob.TaskGroups = []*TaskGroup{{Name: \"web\"}} // no tasks\n// after\njob.TaskGroups = []*TaskGroup{{Name: \"web\", Count: 1, Tasks: []*Task{{Name: \"server\", Driver: \"docker\", Config: map[string]interface{}{\"image\": \"nginx\"}}}}}","handlingStrategy":"validation","validationCode":"// Pre-submit check mirroring nomad job validate\nfor _, tg := range job.TaskGroups {\n    if len(tg.Tasks) == 0 {\n        return fmt.Errorf(\"task group %q has no tasks\", tg.Name)\n    }\n}\nif err := job.Validate(); err != nil { return err }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run `nomad job validate` in CI before `nomad job run`.","Keep task group stanzas complete (tasks, count, network) when templating.","Read the full multi-error output — each group reports its own failure."],"tags":["nomad","job-validation","task-group","hcl"],"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"}