kubernetes/kops · error

could not find any non-overlapping CIDRs in parent NetworkCI

Error message

could not find any non-overlapping CIDRs in parent NetworkCIDR; cannot automatically assign CIDR to subnet

What it means

kOps splits the parent NetworkCIDR into candidate child CIDRs and filters out ones overlapping with explicitly-specified (reserved) subnets. When every candidate overlaps or the parent is too small, automatic CIDR assignment is impossible, so kOps refuses to guess and fails loudly.

Source

Thrown at upup/pkg/fi/cloudup/subnets.go:209

	// Remove any CIDRs marked as overlapping
	{
		var nonOverlapping []*net.IPNet
		for _, c := range bigCIDRs {
			overlapped := false
			for _, r := range reserved {
				if subnet.Overlap(r, c) {
					overlapped = true
				}
			}
			if !overlapped {
				nonOverlapping = append(nonOverlapping, c)
			}
		}
		bigCIDRs = nonOverlapping
	}

	if len(bigCIDRs) == 0 {
		return fmt.Errorf("could not find any non-overlapping CIDRs in parent NetworkCIDR; cannot automatically assign CIDR to subnet")
	}

	// Assign CIDRs to little subnets
	if len(littleSubnets) > 0 {
		littleCIDRs, err := subnet.SplitInto8(bigCIDRs[0])
		if err != nil {
			return err
		}
		bigCIDRs = bigCIDRs[1:]

		for _, subnet := range littleSubnets {
			if subnet.CIDR != "" {
				continue
			}

			if len(littleCIDRs) == 0 {
				return fmt.Errorf("insufficient (little) CIDRs remaining for automatic CIDR allocation to subnet %q", subnet.Name)
			}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Enlarge cluster.spec.networkCIDR (or add a non-overlapping additionalNetworkCIDR) so free space remains
  2. Remove or shrink explicit subnet CIDRs that reserve overlapping space, letting kOps carve them automatically
  3. Move some subnets onto a separate networkCIDR / delete unused subnets before re-running update

Example fix

// before
spec:
  networkCIDR: 10.0.0.0/28  # too small for all subnets
// after
spec:
  networkCIDR: 10.0.0.0/16
Defensive patterns

Strategy: validation

Validate before calling

_, network, _ := net.ParseCIDR(c.Spec.NetworkCIDR)
var reserved []*net.IPNet
for _, s := range c.Spec.Networking.Subnets {
	if s.CIDR != "" {
		if _, sn, err := net.ParseCIDR(s.CIDR); err == nil { reserved = append(reserved, sn) }
	}
}
// ensure network has room outside all reserved subnets before auto-assign

Type guard

func hasFreeSpace(network *net.IPNet, reserved []*net.IPNet) bool {
	for _, r := range reserved { if subnet.SubnetContains(network, r) && r.String() == network.String() { return false } }
	return true
}

Try / catch

if err := PerformAssignments(c, cloud); err != nil {
	if strings.Contains(err.Error(), "non-overlapping CIDRs") { /* enlarge networkCIDR or drop explicit CIDRs */ }
	return err
}

Prevention

When it happens

Trigger: Auto-allocation requested (subnets without cidr) while the parent networkCIDR is too small or fully consumed by explicitly reserved subnet CIDRs — e.g. a /24 network with reserved subnets covering all of it.

Common situations: Cluster grown over time until explicitly-assigned subnet CIDRs exhaust the networkCIDR; shrinking networkCIDR during an upgrade; many utility/internal subnets each reserving space.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/058c16e10c10a733. Report an issue: GitHub.