{"record":{"id":"6d18dd203ce04d19","repo":"hashicorp/nomad","slug":"error-parsing-reserved-ports-w","errorCode":null,"errorMessage":"error parsing reserved_ports: %w","messagePattern":"error parsing reserved_ports: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/network.go","lineNumber":230,"sourceCode":"\n\t// Reserved ports get merged downward. For example given an agent\n\t// config:\n\t//\n\t// client.reserved.reserved_ports = \"22\"\n\t// client.host_network[\"eth0\"] = {reserved_ports = \"80,443\"}\n\t// client.host_network[\"eth1\"] = {reserved_ports = \"1-1000\"}\n\t//\n\t// Addresses on taskNetworks reserve port 22\n\t// Addresses on eth0 reserve 22,80,443 (note 22 is also reserved!)\n\t// Addresses on eth1 reserve 1-1000\n\tglobalResPorts := []uint{}\n\n\tif node.ReservedResources != nil && node.ReservedResources.Networks.ReservedHostPorts != \"\" {\n\t\tresPorts, err := ParsePortRanges(node.ReservedResources.Networks.ReservedHostPorts)\n\t\tif err != nil {\n\t\t\t// This is a fatal error that should have been\n\t\t\t// prevented by client validation.\n\t\t\treturn fmt.Errorf(\"error parsing reserved_ports: %w\", err)\n\t\t}\n\n\t\tglobalResPorts = make([]uint, len(resPorts))\n\t\tfor i, p := range resPorts {\n\t\t\tglobalResPorts[i] = uint(p)\n\t\t}\n\t}\n\n\t// Filter task networks down to those with a device. For example\n\t// taskNetworks may contain a \"bridge\" interface which has no device\n\t// set and cannot be used to fulfill asks.\n\tfor _, n := range taskNetworks {\n\t\tif n.Device != \"\" {\n\t\t\tidx.TaskNetworks = append(idx.TaskNetworks, n)\n\t\t\tidx.AvailBandwidth[n.Device] = n.MBits\n\n\t\t\t// Reserve ports\n\t\t\tused := idx.getUsedPortsFor(n.IP)","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/network.go#L212-L248","documentation":"SetNode on the network index failed to parse the node-level reserved host ports string (node.ReservedResources.Networks.ReservedHostPorts). ParsePortRanges rejected the value, so the scheduler cannot build its port-usage bitmap and the node is rejected/registration fails. The comment notes clients should have validated this, so it signals data that bypassed client-side validation.","triggerScenarios":"A node registers (or fingerprints update) with reserved_resources.networks.reserved_host_ports containing malformed port ranges — e.g. \"foo\", \"70000-80000\", \"20-10\" (reversed), or overlapping/garbage ranges — and SetNode is invoked during scheduling (AllocsFit) or tests.","commonSituations":"Hand-edited client config files with a bad reserved_ports list; versions/paths where client validation was skipped; state store contents written by a buggy or older client; automation writing invalid port strings into node reserved resources.","solutions":["Fix the client's reserved_ports config to a valid comma-separated list/ranges of ports within 0-65535, ascending ranges (e.g. \"22, 5900-5950\")","Validate the port string locally with the same rules (ParsePortRanges semantics) before registering/updating the node","If the bad value is already in state, deregister and re-register the node after fixing config","Upgrade clients so reserved port values are validated before being sent to servers"],"exampleFix":"// before (client config)\nreserved_ports = \"22, 100-50, http\"\n// after\nreserved_ports = \"22, 100-200\"","handlingStrategy":"validation","validationCode":"func validPortList(s string) bool {\n\tif s == \"\" { return true }\n\tfor _, part := range strings.Split(s, \",\") {\n\t\tpart = strings.TrimSpace(part)\n\t\tlo, hi, found := strings.Cut(part, \"-\")\n\t\ta, err1 := strconv.Atoi(strings.TrimSpace(lo))\n\t\tb, err2 := a, error(nil)\n\t\tif found { b, err2 = strconv.Atoi(strings.TrimSpace(hi)) }\n\t\tif err1 != nil || err2 != nil || a < 0 || b > 65535 || (found && a > b) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"if err := client.Nodes().Update(node); err != nil && strings.Contains(err.Error(), \"error parsing reserved_ports\") {\n\t// fix node reserved_resources.networks.reserved_host_ports and retry once\n}","preventionTips":["Keep reserved host ports as ascending numeric ranges within 0-65535 (e.g. \"22, 5900-5950\")","Use nomad agent config validation before starting clients with reserved_ports","Avoid hand-editing node reserved resources; let the client fingerprint/config path set them","Re-register nodes after changing reserved port configuration"],"tags":["nomad","scheduler","ports","network","validation"],"backgroundTag":"invalid-port-range","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"}