{"record":{"id":"0189eecc9519ee96","repo":"cilium/cilium","slug":"unable-to-parse-cidrrule-q-w","errorCode":null,"errorMessage":"unable to parse CIDRRule %q: %w","messagePattern":"unable to parse CIDRRule %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/policy/api/rule_validation.go","lineNumber":832,"sourceCode":"\t\t\treturn fmt.Errorf(\"failed to sanitize cidrGroupSelector %v: %w\", c.CIDRGroupSelector.String(), err)\n\t\t}\n\t}\n\tif cnt == 0 {\n\t\treturn fmt.Errorf(\"one of cidr, cidrGroupRef, or cidrGroupSelector is required\")\n\t}\n\tif cnt > 1 {\n\t\treturn fmt.Errorf(\"more than one of cidr, cidrGroupRef, or cidrGroupSelector may not be set\")\n\t}\n\n\tif len(c.CIDRGroupRef) > 0 || c.CIDRGroupSelector.LabelSelector != nil {\n\t\treturn nil // these are selectors;\n\t}\n\n\t// Only allow notation <IP address>/<prefix>. Note that this differs from\n\t// the logic in api.CIDR.Sanitize().\n\tprefix, err := netip.ParsePrefix(string(c.Cidr))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to parse CIDRRule %q: %w\", c.Cidr, err)\n\t}\n\n\tprefixLength := prefix.Bits()\n\tif prefixLength < 0 {\n\t\treturn fmt.Errorf(\"CIDR cannot specify non-contiguous mask %s\", prefix)\n\t}\n\n\t// Ensure that each provided exception CIDR prefix  is formatted correctly,\n\t// and is contained within the CIDR prefix to/from which we want to allow\n\t// traffic.\n\tfor _, p := range c.ExceptCIDRs {\n\t\texcept, err := netip.ParsePrefix(string(p))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Note: this also checks that the allow CIDR prefix and the exception\n\t\t// CIDR prefixes are part of the same address family.","sourceCodeStart":814,"sourceCodeEnd":850,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/policy/api/rule_validation.go#L814-L850","documentation":"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.","triggerScenarios":"(*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'.","commonSituations":"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.","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."],"exampleFix":"// before\n{\"fromCIDR\": [{\"cidr\": \"10.0.0.1\"}]}\n// after\n{\"fromCIDR\": [{\"cidr\": \"10.0.0.1/32\"}]}","handlingStrategy":"validation","validationCode":"import \"net/netip\"\nfunc isParsableCIDR(s string) bool {\n\t_, err := netip.ParsePrefix(s)\n\treturn err == nil\n}","typeGuard":null,"tryCatchPattern":"if err := rule.Validate(); err != nil {\n\tvar perr *net.ParseError\n\tif errors.As(err, &perr) { /* fix cidr notation */ }\n\treturn fmt.Errorf(\"policy import rejected: %w\", err)\n}","preventionTips":["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"],"tags":["cilium","network-policy","cidr","parse-error"],"backgroundTag":"invalid-cidr-notation","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}