cilium/cilium · error

failed to set reserved ranges for CIDR %s: %w

Error message

failed to set reserved ranges for CIDR %s: %w

What it means

setReservedRanges configures each pool allocator with reserved IP ranges (e.g. the node/service-excluded ranges) by calling SetReservedRanges on every CIDRAllocator of the pool, invoked from UpsertPool. When an allocator rejects the ranges, the error is wrapped with the offending CIDR prefix. This usually means the reserved ranges do not fit or validate within that allocator's CIDR.

Source

Thrown at operator/pkg/ipam/allocator/multipool/pool_allocator.go:309

	for i := range cidrs {
		cidrConfig := &cidrs[i]
		prefixes = append(prefixes, cidrConfig.cidr)
	}

	return prefixes
}

func setReservedRanges(allocators []cidralloc.CIDRAllocator, cidrs []poolCIDRConfig) error {
	reservedRanges := make(map[netip.Prefix][]netipx.IPRange, len(cidrs))
	for i := range cidrs {
		cidrConfig := &cidrs[i]
		reservedRanges[cidrConfig.cidr] = cidrConfig.reservedRanges
	}

	for i := range allocators {
		prefix := allocators[i].Prefix()
		if err := allocators[i].SetReservedRanges(reservedRanges[prefix]); err != nil {
			return fmt.Errorf("failed to set reserved ranges for CIDR %s: %w", prefix, err)
		}
	}

	return nil
}

func (p *PoolAllocator) UpsertPool(poolName string, ipv4CIDRs []poolCIDRConfig, ipv4MaskSize int, ipv6CIDRs []poolCIDRConfig, ipv6MaskSize int, opts ...PoolOption) error {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	var options poolOptions
	for _, opt := range opts {
		opt(&options)
	}

	pool, exists := p.pools[poolName]
	if exists && ipv4MaskSize != pool.v4MaskSize {
		return fmt.Errorf("cannot change IPv4 mask size in existing pool %q", poolName)

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Validate the pool's reservedRanges in the CiliumPodIPPool spec: each range must be inside the matching pool CIDR, with start <= end and valid IPs of the same family.
  2. Compare the prefix printed in the error against the reservedRanges map key — fix the mismatched CIDR entry in the pool spec.
  3. Re-apply a known-good CiliumPodIPPool (kubectl get ciliumpodippool <name> -o yaml, correct, kubectl apply) so UpsertPool succeeds on the next sync.
  4. If ranges come from config/helm values, fix the values and upgrade rather than editing the object ad hoc, to avoid drift on the next sync.

Example fix

// before: reserved range outside pool CIDR
cidrs:
- cidr: "10.0.0.0/16"
  reservedRanges: [{"start": "192.168.1.1", "end": "192.168.1.10"}]
// after: range contained in the pool CIDR
cidrs:
- cidr: "10.0.0.0/16"
  reservedRanges: [{"start": "10.0.0.1", "end": "10.0.0.10"}]
Defensive patterns

Strategy: validation

Validate before calling

// validate pool reserved ranges before UpsertPool
for _, cc := range cidrConfigs {
	prefix := netip.MustParsePrefix(cc.cidr)
	for _, r := range cc.reservedRanges {
		start, end := netip.MustParseAddr(r.Start), netip.MustParseAddr(r.End)
		if !prefix.Contains(start) || !prefix.Contains(end) || start.Compare(end) > 0 {
			return fmt.Errorf("reserved range %s-%s invalid for %s", r.Start, r.End, cc.cidr)
		}
	}
}

Type guard

func reservedRangeValid(prefix netip.Prefix, start, end netip.Addr) bool {
	return prefix.Contains(start) && prefix.Contains(end) && start.Compare(end) <= 0
}

Try / catch

if err := p.UpsertPool(ctx, pool); err != nil {
	if strings.Contains(err.Error(), "failed to set reserved ranges") {
		log.Error("fix CiliumPodIPPool reservedRanges (must be inside pool CIDR, start<=end)", "err", err)
	}
	return err
}

Prevention

When it happens

Trigger: UpsertPool is called with a CiliumPodIPPool whose reservedRanges (per-CIDR) are invalid for the allocator's prefix — e.g. a reserved range not contained in the pool CIDR, a range whose start/end are inverted, misformatted IPs, or reserved ranges supplied for a CIDR that is not part of the pool.

Common situations: Typo or wrong subnet in the pool's reservedRanges spec; reserved ranges defined per-CIDR don't match the allocator prefix after a CIDR edit; IPv4/IPv6 values swapped in the pool spec; overlapping/inverted ranges (first > last) failing validation.

Related errors


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