hashicorp/nomad · error

Service %s is invalid: may only specify task the service bel

Error message

Service %s is invalid: may only specify task the service belongs to, got %q

What it means

A task-level service set its task_name to a task other than the one containing it. Task services may only reference their own task, so validation rejects any service.TaskName that is non-empty and differs from task.Name.

Source

Thrown at nomad/structs/structs.go:7493

	// Accumulate the providers used for this task group. Currently, Nomad only
	// allows the use of a single service provider within a task group.
	providerSet := set.New[string](1)

	// Create a map of known tasks and their services so we can compare
	// vs the group-level services and checks
	for _, task := range tg.Tasks {
		taskSet.Insert(task.Name)

		if len(task.Services) == 0 {
			continue
		}

		for _, service := range task.Services {

			// Ensure no task-level service can only specify the task it belongs to.
			if service.TaskName != "" && service.TaskName != task.Name {
				mErr.Errors = append(mErr.Errors,
					fmt.Errorf("Service %s is invalid: may only specify task the service belongs to, got %q", service.Name, service.TaskName),
				)
			}

			// Ensure no task-level checks can only specify the task they belong to.
			for _, check := range service.Checks {
				if check.TaskName != "" && check.TaskName != task.Name {
					mErr.Errors = append(mErr.Errors,
						fmt.Errorf("Check %s is invalid: may only specify task the check belongs to, got %q", check.Name, check.TaskName),
					)
				}
			}

			// Track that we have seen this service id
			id := unique{service.Name, task.Name, service.PortLabel}
			if !idSet.Insert(id) {
				// accumulate duplicates for a single error later on
				idDuplicateSet.Insert(id)
			}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the task field from the task-level service so it defaults to the enclosing task.
  2. Set task to exactly the name of the task containing the service.
  3. Move the service to the group-level services block if it genuinely targets another task's context.

Example fix

// before
task "web" { service { name="s" task="api" } }
// after
task "web" { service { name="s" } }
Defensive patterns

Strategy: validation

Validate before calling

if svc.TaskName != "" && svc.TaskName != enclosingTaskName {
  return fmt.Errorf("service %q: task %q != enclosing %q", svc.Name, svc.TaskName, enclosingTaskName)
}

Prevention

When it happens

Trigger: Inside a task's services block, setting task = "other-task" where other-task is not the enclosing task; detected during group/task validation of the submitted job.

Common situations: Moving a service stanza from one task to another but leaving the old task name; copy-paste of group-level service config that included a task field; templating that substitutes the wrong task name.

Related errors


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