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
- Correct rr.End to a valid bare IP literal in the same family as the pool CIDR.
- Ensure the field is actually populated (check YAML structure/indentation).
- Remove any prefix length or zone notation from the value.
- 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
- Verify End is populated and matches the pool's address family.
- Lint YAML structure so values do not shift between fields.
- Copy ranges within the same family only.
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
- invalid reserved range start %q in pool CIDR %s: %w
- invalid IPv4 CIDR config: %w
- invalid IPv6 CIDR config: %w
- invalid reserved range %s-%s in pool CIDR %s
- reserved range %s-%s is outside pool CIDR %s
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/bf974f9fe4b663ed.
Report an issue: GitHub.