cilium/cilium · error

invalid reserved range end %q in pool CIDR %s: %w

Error message

invalid reserved range end %q in pool CIDR %s: %w

What it means

parseReservedRanges could not parse the End field of a ReservedRange as an IP address via netip.ParseAddr. Mirrors the start-address failure but for the range's end value; the netip parse error is wrapped and both the value and pool CIDR are reported.

Source

Thrown at operator/pkg/ipam/allocator/multipool/pool_handler.go:196

			cidr:           prefix,
			reservedRanges: reservedRanges,
		})
	}

	return configs, nil
}

func parseReservedRanges(poolCIDR netip.Prefix, ranges []v2.ReservedRange) ([]netipx.IPRange, error) {
	reserved := make([]netipx.IPRange, 0, len(ranges))
	for _, rr := range ranges {
		start, err := netip.ParseAddr(rr.Start)
		if err != nil {
			return nil, fmt.Errorf("invalid reserved range start %q in pool CIDR %s: %w", rr.Start, poolCIDR, err)
		}

		end, err := netip.ParseAddr(rr.End)
		if err != nil {
			return nil, fmt.Errorf("invalid reserved range end %q in pool CIDR %s: %w", rr.End, poolCIDR, err)
		}

		r := netipx.IPRangeFrom(start, end)
		if !r.IsValid() {
			return nil, fmt.Errorf("invalid reserved range %s-%s in pool CIDR %s", start, end, poolCIDR)
		}

		if !poolCIDR.Contains(start) || !poolCIDR.Contains(end) {
			return nil, fmt.Errorf("reserved range %s-%s is outside pool CIDR %s", start, end, poolCIDR)
		}

		reserved = append(reserved, r)
	}

	return reserved, nil
}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Correct rr.End to a valid bare IP literal in the same family as the pool CIDR.
  2. Ensure the field is actually populated (check YAML structure/indentation).
  3. Remove any prefix length or zone notation from the value.
  4. Pre-validate with netip.ParseAddr in tooling or admission webhooks.

Example fix

// before
reservedRanges: [{start: "10.0.0.240", end: "10.0.0.255/32"}]
// after
reservedRanges: [{start: "10.0.0.240", end: "10.0.0.255"}]
Defensive patterns

Strategy: validation

Validate before calling

for _, rr := range ranges {
    if _, err := netip.ParseAddr(rr.End); err != nil {
        return fmt.Errorf("ReservedRange.End %q is not a valid IP: %w", rr.End, err)
    }
}

Type guard

func isValidEndIP(s string) bool {
    _, err := netip.ParseAddr(s)
    return err == nil && s != ""
}

Try / catch

if _, err := netip.ParseAddr(rr.End); err != nil {
    return fmt.Errorf("invalid reserved range end %q: use a bare IP literal", rr.End)
}

Prevention

When it happens

Trigger: A v2.ReservedRange in a pool's PoolCIDRConfig has rr.End that is not a valid IP literal: empty string, hostname, CIDR notation, out-of-family value for an IPv6 pool, or typographical error.

Common situations: Typos when reserving the last addresses of a range; copy-paste from IPv4 config into IPv6 pool; YAML indentation errors leaving End empty or shifted into another field.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/bf974f9fe4b663ed. Report an issue: GitHub.