{"record":{"id":"fc407270c4032d68","repo":"hashicorp/nomad","slug":"services-are-not-unique-s","errorCode":null,"errorMessage":"Services are not unique: %s","messagePattern":"Services are not unique: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":7559,"sourceCode":"\n\t\tfor _, check := range service.Checks {\n\t\t\tif check.TaskName != \"\" {\n\t\t\t\tif check.AddressMode == AddressModeDriver {\n\t\t\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Check %q invalid: cannot use address_mode=\\\"driver\\\", only checks defined in a \\\"task\\\" service block can use this mode\", service.Name))\n\t\t\t\t}\n\t\t\t\tif !taskSet.Contains(check.TaskName) {\n\t\t\t\t\tmErr.Errors = append(mErr.Errors,\n\t\t\t\t\t\tfmt.Errorf(\"Check %s invalid: refers to non-existent task %s\", check.Name, check.TaskName))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Produce an error of any services which are not unique enough in the group\n\t// i.e. have same <task, name, port>\n\tif idDuplicateSet.Size() > 0 {\n\t\tmErr.Errors = append(mErr.Errors,\n\t\t\tfmt.Errorf(\n\t\t\t\t\"Services are not unique: %s\",\n\t\t\t\tidDuplicateSet.StringFunc(\n\t\t\t\t\tfunc(u unique) string {\n\t\t\t\t\t\ts := u.task + \"->\" + u.name\n\t\t\t\t\t\tif u.port != \"\" {\n\t\t\t\t\t\t\ts += \":\" + u.port\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn s\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\t}\n\n\t// The initial feature release of native service discovery only allows for\n\t// a single service provider to be used across all services in a task\n\t// group.\n\tif providerSet.Size() > 1 {","sourceCodeStart":7541,"sourceCodeEnd":7577,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L7541-L7577","documentation":"During TaskGroup validation in nomad/structs/structs.go, Nomad collects services whose <task, name, port> tuple is duplicated within the group and fails validation. Job specs must have unique service identity per task/name/port combination so that service registration and discovery are unambiguous.","triggerScenarios":"Submitting a job where a task group (or its tasks) declares two services with the same name pointing at the same task and the same port label — e.g. two `service { name = \"http\" port = \"http\" }` blocks attached to the same task.","commonSituations":"Copy-pasting a service block to add a second check instead of adding checks to the existing service; templating loops that generate services with an identical name; forgetting that group-level and task-level services share the uniqueness constraint.","solutions":["Rename one of the duplicate services so each <task, name, port> tuple is unique","If you only need more checks, move the extra checks into the existing service's `check` blocks instead of duplicating the service","Parameterize your template/generator so service names include the task or port they target"],"exampleFix":"// before\nservice { name = \"web\" port = \"http\" }\nservice { name = \"web\" port = \"http\" }\n// after\nservice {\n  name = \"web\"\n  port = \"http\"\n  check { type = \"http\" path = \"/health\" }\n}","handlingStrategy":"validation","validationCode":"names := map[string]bool{}\nfor _, svc := range group.Services {\n  key := svc.Task + \"->\" + svc.Name + \":\" + svc.Port\n  if names[key] { return fmt.Errorf(\"duplicate service %q\", key) }\n  names[key] = true\n}","typeGuard":"func uniqueServices(svcs []*api.Service) bool {\n  seen := map[string]bool{}\n  for _, s := range svcs {\n    k := s.TaskName + \"->\" + s.Name + \":\" + s.PortLabel\n    if seen[k] { return false }\n    seen[k] = true\n  }\n  return true\n}","tryCatchPattern":null,"preventionTips":["Add a CI step running `nomad job validate` on every job file","Generate service names from task+port in templates to guarantee uniqueness","Consolidate multiple checks into one service block"],"tags":["nomad","job-validation","services"],"backgroundTag":"duplicate-resource-definition","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"}