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
- Convert the value to strict CIDR notation with an explicit prefix length: '10.0.0.1' → '10.0.0.1/32'.
- Replace netmask-style masks with prefix lengths: '10.0.0.0/255.0.0.0' → '10.0.0.0/8'.
- Run the string through Go netip.ParsePrefix (or `ipcalc`) locally to verify before importing.
- 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
- Always write CIDRs as <IP>/<prefix-length>; use /32 and /128 for single hosts
- Never use netmask notation (255.0.0.0) in cidr fields
- Dry-run values through netip.ParsePrefix in tooling before generating policy
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unable to parse CIDR: %w
- unable to parse port: %w
- IP must be specified
- CIDR cannot specify non-contiguous mask %s
- one of cidr, cidrGroupRef, or cidrGroupSelector is required
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/0189eecc9519ee96.
Report an issue: GitHub.