hashicorp/nomad · error
error parsing reserved_ports: %w
Error message
error parsing reserved_ports: %w
What it means
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.
Source
Thrown at nomad/structs/network.go:230
// Reserved ports get merged downward. For example given an agent
// config:
//
// client.reserved.reserved_ports = "22"
// client.host_network["eth0"] = {reserved_ports = "80,443"}
// client.host_network["eth1"] = {reserved_ports = "1-1000"}
//
// Addresses on taskNetworks reserve port 22
// Addresses on eth0 reserve 22,80,443 (note 22 is also reserved!)
// Addresses on eth1 reserve 1-1000
globalResPorts := []uint{}
if node.ReservedResources != nil && node.ReservedResources.Networks.ReservedHostPorts != "" {
resPorts, err := ParsePortRanges(node.ReservedResources.Networks.ReservedHostPorts)
if err != nil {
// This is a fatal error that should have been
// prevented by client validation.
return fmt.Errorf("error parsing reserved_ports: %w", err)
}
globalResPorts = make([]uint, len(resPorts))
for i, p := range resPorts {
globalResPorts[i] = uint(p)
}
}
// Filter task networks down to those with a device. For example
// taskNetworks may contain a "bridge" interface which has no device
// set and cannot be used to fulfill asks.
for _, n := range taskNetworks {
if n.Device != "" {
idx.TaskNetworks = append(idx.TaskNetworks, n)
idx.AvailBandwidth[n.Device] = n.MBits
// Reserve ports
used := idx.getUsedPortsFor(n.IP)View on GitHub (pinned to 482b49bf1a)
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
Example fix
// before (client config) reserved_ports = "22, 100-50, http" // after reserved_ports = "22, 100-200"
Defensive patterns
Strategy: validation
Validate before calling
func validPortList(s string) bool {
if s == "" { return true }
for _, part := range strings.Split(s, ",") {
part = strings.TrimSpace(part)
lo, hi, found := strings.Cut(part, "-")
a, err1 := strconv.Atoi(strings.TrimSpace(lo))
b, err2 := a, error(nil)
if found { b, err2 = strconv.Atoi(strings.TrimSpace(hi)) }
if err1 != nil || err2 != nil || a < 0 || b > 65535 || (found && a > b) {
return false
}
}
return true
} Try / catch
if err := client.Nodes().Update(node); err != nil && strings.Contains(err.Error(), "error parsing reserved_ports") {
// fix node reserved_resources.networks.reserved_host_ports and retry once
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- error parsing reserved_ports for network %q: %w
- network hostname %q is not a valid DNS name
- hostname cannot be set on task group using %q networking mod
- timeout cannot be negative
- bitmap must be positive size
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/6d18dd203ce04d19.
Report an issue: GitHub.