hashicorp/nomad · error

Only one task may be marked as leader

Error message

Only one task may be marked as leader

What it means

TaskGroup.Validate counts tasks with `leader = true` and rejects a group with more than one leader task. Only a single task may be designated leader because Nomad uses the leader flag to decide which task's exit signals shutdown of the whole allocation.

Source

Thrown at nomad/structs/structs.go:7271

		if task.Name == "" {
			mErr = multierror.Append(mErr, fmt.Errorf("Task %d missing name", idx+1))
		} else if existing, ok := tasks[task.Name]; ok {
			mErr = multierror.Append(mErr, fmt.Errorf("Task %d redefines '%s' from task %d", idx+1, task.Name, existing+1))
		} else {
			tasks[task.Name] = idx
		}

		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))
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set `leader = true` on exactly one task in the group; remove the flag from the others.
  2. If multiple tasks truly lead independent lifecycles, split them into separate task groups.

Example fix

// before
task "api" { leader = true }
task "worker" { leader = true }
// after
task "api" { leader = true }
task "worker" { }
Defensive patterns

Strategy: validation

Validate before calling

// Go: at most one leader per group
for _, tg := range job.TaskGroups {
  leaders := 0
  for _, t := range tg.Tasks {
    if t.Leader {
      leaders++
    }
  }
  if leaders > 1 {
    return fmt.Errorf("group %q has %d leader tasks", tg.Name, leaders)
  }
}

Prevention

When it happens

Trigger: Submitting a job where two or more task blocks in the same group set `leader = true`.

Common situations: Copy-pasting a task stanza including its leader flag; misunderstanding leader semantics and marking several coordination tasks as leaders.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/b1b90c22395a4f53. Report an issue: GitHub.