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
- Remove the task field from the task-level service so it defaults to the enclosing task.
- Set task to exactly the name of the task containing the service.
- 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
- Omit the task field in task-level services
- Only set task on group-level services
- Review diffs when moving service stanzas between scopes
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
- Check %s is invalid: may only specify task the check belongs
- service[%d] %+q validation failed: %s
- expose may only be set for Consul service checks
- on_update may only be set to ignore_warnings for Consul serv
- ignore_warnings on check_restart only supported for Consul s
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/ac3003ede32288bd.
Report an issue: GitHub.