hashicorp/nomad · error
Task group %s must have at least one main task
Error message
Task group %s must have at least one main task
What it means
TaskGroup.Validate requires that a non-empty group contain at least one main task. A group composed entirely of lifecycle-hook tasks (prestart, poststart, poststop) has nothing to run as the primary workload, which is invalid; this error is appended when mainTasks == 0 for a group with tasks.
Source
Thrown at nomad/structs/structs.go:7277
}
if task.Leader {
leaderTasks++
}
if task.IsMain() {
mainTasks++
}
}
if leaderTasks > 1 {
mErr = multierror.Append(mErr, fmt.Errorf("Only one task may be marked as leader"))
}
// A task group made up entirely of lifecycle tasks (prestart, poststart, or
// poststop) has no main task to run, which is invalid.
if len(tg.Tasks) > 0 && mainTasks == 0 {
mErr = multierror.Append(mErr, fmt.Errorf("Task group %s must have at least one main task", tg.Name))
}
// Validate the volume requests
var canaries int
if tg.Update != nil {
canaries = tg.Update.Canary
}
for name, volReq := range tg.Volumes {
if err := volReq.Validate(j.Type, tg.Count, canaries); err != nil {
mErr = multierror.Append(mErr, fmt.Errorf(
"Task group volume validation for %s failed: %v", name, err))
}
}
// Validate task group and task network resources
if err := tg.validateNetworks(); err != nil {
outer := fmt.Errorf("Task group network validation failed: %v", err)
mErr = multierror.Append(mErr, outer)View on GitHub (pinned to 482b49bf1a)
Solutions
- Add a main task (a task without a lifecycle stanza) to the group.
- Or remove the orphaned lifecycle-only tasks and attach them as sidecars to a group that has a main task.
Example fix
// before
group "g" {
task "init" {
lifecycle { hook = "prestart" }
}
}
// after
group "g" {
task "init" {
lifecycle { hook = "prestart" }
}
task "app" { driver = "docker" }
} Defensive patterns
Strategy: validation
Validate before calling
// Go: ensure each non-empty group has a main task
for _, tg := range job.TaskGroups {
if len(tg.Tasks) == 0 {
continue
}
mains := 0
for _, t := range tg.Tasks {
if !t.IsMain() {
mains++
}
}
if mains == 0 {
return fmt.Errorf("group %q has no main task", tg.Name)
}
} Prevention
- Pair every lifecycle (prestart/poststart/poststop) task with a main task in the same group.
- Audit groups after moving tasks between groups.
- Validate specs in CI with `nomad job validate`.
When it happens
Trigger: Submitting a group whose tasks all set `lifecycle { hook = "prestart"/"poststart"/"poststop" }` with no task left as a main (non-lifecycle) task.
Common situations: Refactoring a job into init-container style helpers and forgetting the main workload; moving the only main task into another group while leaving its lifecycle sidecars behind.
Related errors
- ErrConnectRequireOneNetwork
- ErrConnectInvalidNetworkMode
- service.port must be set for mesh gateway service
- non-default Consul cluster requires Nomad Enterprise
- numa scheduling requires Nomad Enterprise
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e8aa8341fc1a5b1b.
Report an issue: GitHub.