{"record":{"id":"e160ad35074610e2","repo":"hashicorp/nomad","slug":"static-port-d-already-reserved-by-s","errorCode":null,"errorMessage":"Static port %d already reserved by %s","messagePattern":"Static port (.+?) already reserved by (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":7354,"sourceCode":"\t\t\tif other, ok := portLabels[port.Label]; ok {\n\t\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Port label %s already in use by %s\", port.Label, other))\n\t\t\t} else {\n\t\t\t\tportLabels[port.Label] = \"taskgroup network\"\n\t\t\t}\n\n\t\t\tif port.Value != 0 {\n\t\t\t\thostNetwork := port.HostNetwork\n\t\t\t\tif hostNetwork == \"\" {\n\t\t\t\t\thostNetwork = \"default\"\n\t\t\t\t}\n\t\t\t\tstaticPorts, ok := staticPortsIndex[hostNetwork]\n\t\t\t\tif !ok {\n\t\t\t\t\tstaticPorts = make(map[int]string)\n\t\t\t\t}\n\t\t\t\t// static port\n\t\t\t\tif other, ok := staticPorts[port.Value]; ok {\n\t\t\t\t\tif !port.IgnoreCollision {\n\t\t\t\t\t\terr := fmt.Errorf(\"Static port %d already reserved by %s\", port.Value, other)\n\t\t\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t\t\t}\n\t\t\t\t} else if port.Value > math.MaxUint16 {\n\t\t\t\t\terr := fmt.Errorf(\"Port %s (%d) cannot be greater than %d\", port.Label, port.Value, math.MaxUint16)\n\t\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t\t} else {\n\t\t\t\t\tstaticPorts[port.Value] = fmt.Sprintf(\"taskgroup network:%s\", port.Label)\n\t\t\t\t\tstaticPortsIndex[hostNetwork] = staticPorts\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif port.To < -1 {\n\t\t\t\terr := fmt.Errorf(\"Port %q cannot be mapped to negative value %d\", port.Label, port.To)\n\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t} else if port.To > math.MaxUint16 {\n\t\t\t\terr := fmt.Errorf(\"Port %q cannot be mapped to a port (%d) greater than %d\", port.Label, port.To, math.MaxUint16)\n\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t}","sourceCodeStart":7336,"sourceCodeEnd":7372,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L7336-L7372","documentation":"Raised by TaskGroup.validateNetworks when two static ports with the same numeric value are reserved on the same host_network, and the port does not set `IgnoreCollision`. Nomad tracks reserved static ports per host network (default when unset) and rejects the job to prevent host port conflicts.","triggerScenarios":"Defining two `port` entries with the same fixed `static = <value>` (or ReservedPorts with equal Value) in the same task group/host_network, without `ignore_collision = true` on the later port.","commonSituations":"Hard-coding well-known ports (8080, 9090) in multiple services of one group; consolidating services into one job where each previously reserved the same host port; migrating compose files that mapped identical host ports twice.","solutions":["Change one of the conflicting static ports to a different value","Convert the conflicting port to a dynamic port (`port \"http\" {}` with no static value) and let Nomad allocate it","Set `ignore_collision = true` on the port if overlap is intentionally acceptable (host network mode only)","Ensure ports conflicting across different host_networks use distinct `host_network` values"],"exampleFix":"// before\nnetwork {\n  port \"web\"  { static = 8080 }\n  port \"admin\" { static = 8080 }\n}\n// after\nnetwork {\n  port \"web\"   { static = 8080 }\n  port \"admin\" { static = 8081 }\n}","handlingStrategy":"validation","validationCode":"func noStaticPortCollisions(tg *api.TaskGroup) error {\n  seen := map[int]string{}\n  for _, n := range tg.Networks {\n    for _, p := range append(n.ReservedPorts, n.DynamicPorts...) {\n      if p.To != 0 && p.Static != 0 { continue } // only static host ports\n      if prev, ok := seen[n.ReservedPortsHash()]; ok { _ = prev }\n    }\n  }\n  // simpler: track static values\n  vals := map[int]string{}\n  for _, n := range tg.Networks {\n    for _, p := range n.ReservedPorts {\n      if other, ok := vals[p.Value]; ok && !p.IgnoreCollision {\n        return fmt.Errorf(\"static port %d reserved twice (%s, %s)\", p.Value, other, p.Label)\n      }\n      vals[p.Value] = p.Label\n    }\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer dynamic ports (`port \"http\" {}` without static) unless a fixed host port is required","Never hard-code the same well-known port for two services in one group","Use distinct host_network assignments when groups must reuse port values","Set ignore_collision = true only when overlap is intentional (host mode only)"],"tags":["nomad","network","ports","host-network"],"backgroundTag":"port-already-in-use","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"}