{"record":{"id":"72cbfe744eb6a23f","repo":"kubernetes/kops","slug":"failed-to-parse-network-cidr-q-w","errorCode":null,"errorMessage":"failed to parse network CIDR %q: %w","messagePattern":"failed to parse network CIDR %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/nodemodel/nodeupconfigbuilder.go","lineNumber":394,"sourceCode":"\tconfig.Packages = append(config.Packages, cluster.Spec.Packages...)\n\tconfig.Packages = append(config.Packages, ig.Spec.Packages...)\n\n\treturn config, bootConfig, nil\n}\n\n// selectControlPlaneIPs narrows the addresses that reach the API server down to the ones a node\n// in this cluster can actually connect to. Some of the addresses may be FQDNs or public IPs.\nfunc selectControlPlaneIPs(cluster *kops.Cluster, apiserverAddresses []string) ([]string, error) {\n\tvar controlPlaneIPs []string\n\n\tswitch cluster.GetCloudProvider() {\n\tcase kops.CloudProviderAWS, kops.CloudProviderHetzner, kops.CloudProviderOpenstack:\n\t\t// Use a private IP address that belongs to the cluster network CIDR, or any IPv6 addresses (some additional addresses may be FQDNs or public IPs)\n\t\tfor _, additionalIP := range apiserverAddresses {\n\t\t\tfor _, networkCIDR := range append(cluster.Spec.Networking.AdditionalNetworkCIDRs, cluster.Spec.Networking.NetworkCIDR) {\n\t\t\t\tcidr, err := netip.ParsePrefix(networkCIDR)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"failed to parse network CIDR %q: %w\", networkCIDR, err)\n\t\t\t\t}\n\t\t\t\tip, err := netip.ParseAddr(additionalIP)\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Nodes in an IPv6-only cluster sit in subnets that have no IPv4 CIDR, so an IPv4\n\t\t\t\t// address is unroutable from them even though it is inside the network CIDR. Handing\n\t\t\t\t// one out only stalls bootstrap on an address that can never answer.\n\t\t\t\tif cluster.Spec.IsIPv6Only() && !ip.Is6() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif cidr.Contains(ip) || ip.Is6() {\n\t\t\t\t\tcontrolPlaneIPs = append(controlPlaneIPs, additionalIP)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase kops.CloudProviderGCE:","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodemodel/nodeupconfigbuilder.go#L376-L412","documentation":"During nodeup config generation, kOps matches each API server address against the cluster's network CIDRs to pick control-plane IPs that nodes can reach. Before matching, every CIDR string (AdditionalNetworkCIDRs plus NetworkCIDR) is parsed with netip.ParsePrefix. This error is thrown when one of those CIDR strings is not a valid CIDR prefix, and the underlying netip parse error is wrapped in.","triggerScenarios":"Running `kops toolbox dump`, `kops get cluster -o yaml`-style config building, or any BuildConfig flow for an AWS/Hetzner/Openstack cluster where cluster.spec.networking.networkCIDR or additionalNetworkCIDRs contains a malformed value such as a bare IP (10.0.0.0 without /16), an empty string, or text like 'invalid'.","commonSituations":"Hand-edited cluster.spec.networking in the cluster manifest; IPv4 CIDR pasted into an IPv6-only cluster (or vice versa without a proper /128, /64); additionalNetworkCIDRs added by automation with trailing whitespace or a bare IP; upgrading from an old cluster spec where CIDR validation was looser.","solutions":["Fix the offending CIDR in the cluster spec: `kops edit cluster` and set networkCIDR / additionalNetworkCIDRs to valid prefixes (e.g. 10.0.0.0/16, 2001:db8::/48), then `kops update cluster`.","Check the wrapped netip error in the message: it names the exact bad string; validate it locally with `ipaddress.ip_network(...)` (python) or `netip.ParsePrefix` (Go) before re-running.","Remove empty strings from additionalNetworkCIDRs (an empty list entry parses as an empty-string prefix and fails).","Re-export the cluster spec from the API/Kubernetes state (`kops get cluster -o yaml`) to check for corruption between storage and what the builder sees."],"exampleFix":"// before (cluster.yaml)\nnetworking:\n  networkCIDR: 10.0.0.0\n// after\nnetworking:\n  networkCIDR: 10.0.0.0/16","handlingStrategy":"validation","validationCode":"import \"net/netip\"\n\nfunc validateNetworkCIDRs(networking kops.ClusterNetworkingSpec) error {\n    for _, cidr := range append(networking.AdditionalNetworkCIDRs, networking.NetworkCIDR) {\n        if _, err := netip.ParsePrefix(cidr); err != nil {\n            return fmt.Errorf(\"invalid network CIDR %q: %w\", cidr, err)\n        }\n    }\n    return nil\n}","typeGuard":"func isValidCIDR(s string) bool {\n    _, err := netip.ParsePrefix(s)\n    return s != \"\" && err == nil\n}","tryCatchPattern":"ips, err := selectControlPlaneIPs(cluster, apiserverAddresses)\nif err != nil {\n    var perr *net.ParseError\n    if errors.As(err, &perr) {\n        // malformed CIDR in cluster spec: surface spec field + value\n        return fmt.Errorf(\"cluster networking spec has invalid CIDR: %w\", err)\n    }\n    return err\n}","preventionTips":["Never hand-edit networkCIDR/additionalNetworkCIDRs without validating with kops update cluster --dry-run first","Always include the prefix length (use /16, not a bare IP) in cluster manifests","Lint cluster specs in CI (validate with `kops toolbox template` or schema validation) before applying","When populating additionalNetworkCIDRs programmatically, skip empty strings instead of appending zero values"],"tags":["network","cidr","cluster-spec","configuration","ipv6"],"backgroundTag":"invalid-cidr-notation","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}