{"record":{"id":"ac3003ede32288bd","repo":"hashicorp/nomad","slug":"service-s-is-invalid-may-only-specify-task-the-s","errorCode":null,"errorMessage":"Service %s is invalid: may only specify task the service belongs to, got %q","messagePattern":"Service (.+?) is invalid: may only specify task the service belongs to, got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":7493,"sourceCode":"\t// Accumulate the providers used for this task group. Currently, Nomad only\n\t// allows the use of a single service provider within a task group.\n\tproviderSet := set.New[string](1)\n\n\t// Create a map of known tasks and their services so we can compare\n\t// vs the group-level services and checks\n\tfor _, task := range tg.Tasks {\n\t\ttaskSet.Insert(task.Name)\n\n\t\tif len(task.Services) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, service := range task.Services {\n\n\t\t\t// Ensure no task-level service can only specify the task it belongs to.\n\t\t\tif service.TaskName != \"\" && service.TaskName != task.Name {\n\t\t\t\tmErr.Errors = append(mErr.Errors,\n\t\t\t\t\tfmt.Errorf(\"Service %s is invalid: may only specify task the service belongs to, got %q\", service.Name, service.TaskName),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Ensure no task-level checks can only specify the task they belong to.\n\t\t\tfor _, check := range service.Checks {\n\t\t\t\tif check.TaskName != \"\" && check.TaskName != task.Name {\n\t\t\t\t\tmErr.Errors = append(mErr.Errors,\n\t\t\t\t\t\tfmt.Errorf(\"Check %s is invalid: may only specify task the check belongs to, got %q\", check.Name, check.TaskName),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Track that we have seen this service id\n\t\t\tid := unique{service.Name, task.Name, service.PortLabel}\n\t\t\tif !idSet.Insert(id) {\n\t\t\t\t// accumulate duplicates for a single error later on\n\t\t\t\tidDuplicateSet.Insert(id)\n\t\t\t}","sourceCodeStart":7475,"sourceCodeEnd":7511,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L7475-L7511","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ntask \"web\" { service { name=\"s\" task=\"api\" } }\n// after\ntask \"web\" { service { name=\"s\" } }","handlingStrategy":"validation","validationCode":"if svc.TaskName != \"\" && svc.TaskName != enclosingTaskName {\n  return fmt.Errorf(\"service %q: task %q != enclosing %q\", svc.Name, svc.TaskName, enclosingTaskName)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit the task field in task-level services","Only set task on group-level services","Review diffs when moving service stanzas between scopes"],"tags":["nomad","service","consul","validation"],"backgroundTag":"invalid-service-task-reference","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"}