cilium/cilium · error
invalid reserved range start %q in pool CIDR %s: %w
Error message
invalid reserved range start %q in pool CIDR %s: %w
What it means
parseReservedRanges could not parse the Start field of a ReservedRange as an IP address with netip.ParseAddr, while validating the reserved ranges of a pool CIDR. The offending value and the pool CIDR are included in the message, and the netip error is wrapped.
Source
Thrown at operator/pkg/ipam/allocator/multipool/pool_handler.go:191
if err != nil {
return nil, err
}
configs = append(configs, poolCIDRConfig{
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)
}View on GitHub (pinned to ac7b90affa)
Solutions
- Replace rr.Start with a valid bare IP literal (no /prefix, no hostname), matching the pool CIDR family.
- If a whole subnet should be excluded, express it as start/end pair of first and last addresses instead of CIDR notation.
- Check for unexpanded template variables or empty strings in the manifest.
- Validate with netip.ParseAddr (or a YAML schema check) before applying.
Example fix
// before
reservedRanges: [{start: "10.0.0.0/29", end: "10.0.0.7"}]
// after
reservedRanges: [{start: "10.0.0.0", end: "10.0.0.7"}] Defensive patterns
Strategy: validation
Validate before calling
for _, rr := range ranges {
if _, err := netip.ParseAddr(rr.Start); err != nil {
return fmt.Errorf("ReservedRange.Start %q is not a valid IP: %w", rr.Start, err)
}
} Type guard
func isBareIP(s string) bool {
a, err := netip.ParseAddr(s)
return err == nil && !a.Zone().IsZero() == false && !strings.Contains(s, "/")
} Try / catch
if _, err := netip.ParseAddr(rr.Start); err != nil {
return fmt.Errorf("invalid reserved range start %q: use a bare IP literal", rr.Start)
} Prevention
- Enter bare IPs, never CIDR notation or hostnames, in Start fields.
- Expand YAML templates before validation to catch unexpanded variables.
- Check that Start is non-empty and properly indented in the manifest.
When it happens
Trigger: A v2.ReservedRange in a PoolCIDRConfig (reached via buildPoolCIDRConfigs -> UpsertPool or ParsePoolSpec callers) has rr.Start set to a non-IP string: hostname, CIDR ('10.0.0.1/32'), empty string, port-suffixed value, or malformed IPv6.
Common situations: Typos in reserved range YAML; users putting CIDR notation instead of a bare IP in the start field; template variables left unexpanded; empty fields from partial config merge.
Related errors
- invalid reserved range end %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/bc2b0c445ea3c832.
Report an issue: GitHub.