{"record":{"id":"f491e827d07fc368","repo":"hashicorp/nomad","slug":"service-q-is-duplicate","errorCode":null,"errorMessage":"service %q is duplicate","messagePattern":"service %q is duplicate","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":8496,"sourceCode":"\tknownServices := make(map[string]struct{})\n\tfor i, service := range t.Services {\n\t\tif err := service.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"service[%d] %+q validation failed: %s\", i, service.Name, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\n\t\tif service.AddressMode == AddressModeAlloc {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"service %q cannot use address_mode=\\\"alloc\\\", only services defined in a \\\"group\\\" block can use this mode\", service.Name))\n\t\t}\n\n\t\tif service.AddressMode == AddressModeAllocIPv6 {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"service %q cannot use address_mode=\\\"alloc_ipv6\\\", only services defined in a \\\"group\\\" block can use this mode\", service.Name))\n\t\t}\n\n\t\t// Ensure that services with the same name are not being registered for\n\t\t// the same port\n\t\tif _, ok := knownServices[service.Name+service.PortLabel]; ok {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"service %q is duplicate\", service.Name))\n\t\t}\n\t\tknownServices[service.Name+service.PortLabel] = struct{}{}\n\n\t\tif service.PortLabel != \"\" {\n\t\t\tif service.AddressMode == \"driver\" {\n\t\t\t\t// Numeric port labels are valid for address_mode=driver\n\t\t\t\t_, err := strconv.Atoi(service.PortLabel)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// Not a numeric port label, add it to list to check\n\t\t\t\t\taddServicePort(service.PortLabel, service.Name)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taddServicePort(service.PortLabel, service.Name)\n\t\t\t}\n\t\t}\n\n\t\t// connect block is only allowed on group level\n\t\tif service.Connect != nil {","sourceCodeStart":8478,"sourceCodeEnd":8514,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L8478-L8514","documentation":"Within one task group, two services may not share the same name AND port label. Nomad keys registered services by name+port; a duplicate would produce ambiguous Consul registrations, so validation rejects it with this error. The dedup map `knownServices[name+portLabel]` detects the second occurrence.","triggerScenarios":"Submitting a job whose group (including all nested tasks) defines two service blocks with identical `name` and identical `port`/port_label; note the key is the concatenation name+portLabel, so same name on different ports is allowed.","commonSituations":"Template-generated jobs that emit a service stanza per task with hardcoded names; copy-pasting a service block and forgetting to change the name; two tasks in one group exposing the same port with the same service name.","solutions":["Rename one of the duplicate service blocks to a unique name (e.g. suffix with the task name).","Point one duplicate at a different port label if they were meant to expose distinct endpoints.","Delete the redundant service stanza if it is a copy-paste artifact.","Search the job file for repeated `service { name = ...` entries sharing both name and port."],"exampleFix":"// before\ngroup \"web\" {\n  service { name = \"http\"; port = \"8080\" }\n  service { name = \"http\"; port = \"8080\" }\n}\n\n// after\ngroup \"web\" {\n  service { name = \"http\"; port = \"8080\" }\n  service { name = \"http-admin\"; port = \"8081\" }\n}","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, tg := range job.TaskGroups {\n  for _, t := range tg.Tasks {\n    for _, s := range t.Services {\n      key := s.Name + s.PortLabel\n      if seen[key] {\n        return fmt.Errorf(\"duplicate service %q on port %q in group %q\", s.Name, s.PortLabel, tg.Name)\n      }\n      seen[key] = true\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Suffix service names with the task name when generating jobs from templates","Search job files for repeated service names before submission","Remember uniqueness is name+port; same name on different ports is allowed"],"tags":["nomad","service-validation","duplicate","consul"],"backgroundTag":"duplicate-service-registration","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"}