cilium/cilium · error

unable to parse CIDRRule %q: %w

Error message

unable to parse CIDRRule %q: %w

What it means

When a CIDRRule specifies 'cidr', Validate parses it with netip.ParsePrefix, which only accepts strict <IP>/<prefix-length> notation (e.g. 10.0.0.0/8, fd00::/8). Anything else — a bare IP without a mask, a non-contiguous mask like /255.0.255.0, or malformed text — fails and is wrapped as this error.

Source

Thrown at pkg/policy/api/rule_validation.go:832

			return fmt.Errorf("failed to sanitize cidrGroupSelector %v: %w", c.CIDRGroupSelector.String(), err)
		}
	}
	if cnt == 0 {
		return fmt.Errorf("one of cidr, cidrGroupRef, or cidrGroupSelector is required")
	}
	if cnt > 1 {
		return fmt.Errorf("more than one of cidr, cidrGroupRef, or cidrGroupSelector may not be set")
	}

	if len(c.CIDRGroupRef) > 0 || c.CIDRGroupSelector.LabelSelector != nil {
		return nil // these are selectors;
	}

	// Only allow notation <IP address>/<prefix>. Note that this differs from
	// the logic in api.CIDR.Sanitize().
	prefix, err := netip.ParsePrefix(string(c.Cidr))
	if err != nil {
		return fmt.Errorf("unable to parse CIDRRule %q: %w", c.Cidr, err)
	}

	prefixLength := prefix.Bits()
	if prefixLength < 0 {
		return fmt.Errorf("CIDR cannot specify non-contiguous mask %s", prefix)
	}

	// Ensure that each provided exception CIDR prefix  is formatted correctly,
	// and is contained within the CIDR prefix to/from which we want to allow
	// traffic.
	for _, p := range c.ExceptCIDRs {
		except, err := netip.ParsePrefix(string(p))
		if err != nil {
			return err
		}

		// Note: this also checks that the allow CIDR prefix and the exception
		// CIDR prefixes are part of the same address family.

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Convert the value to strict CIDR notation with an explicit prefix length: '10.0.0.1' → '10.0.0.1/32'.
  2. Replace netmask-style masks with prefix lengths: '10.0.0.0/255.0.0.0' → '10.0.0.0/8'.
  3. Run the string through Go netip.ParsePrefix (or `ipcalc`) locally to verify before importing.
  4. Fix typos/extra slashes in the cidr field.

Example fix

// before
{"fromCIDR": [{"cidr": "10.0.0.1"}]}
// after
{"fromCIDR": [{"cidr": "10.0.0.1/32"}]}
Defensive patterns

Strategy: validation

Validate before calling

import "net/netip"
func isParsableCIDR(s string) bool {
	_, err := netip.ParsePrefix(s)
	return err == nil
}

Try / catch

if err := rule.Validate(); err != nil {
	var perr *net.ParseError
	if errors.As(err, &perr) { /* fix cidr notation */ }
	return fmt.Errorf("policy import rejected: %w", err)
}

Prevention

When it happens

Trigger: (*CIDRRule).Validate() with c.Cidr non-empty and netip.ParsePrefix(string(c.Cidr)) returning an error: bare IP '10.0.0.1', '10.0.0.0/8/16', non-numeric prefix '10.0.0.0/eight', hostname, or address/mask pair '10.0.0.0/255.0.0.0'.

Common situations: Users entering an IP without prefix length in fromCIDR; converting from tools that accept /netmask notation; typos in prefix length; shell expansion mangling values in generated policies.

Understand the failure class

Related errors


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