kubernetes/kops · critical
failed to parse network CIDR %q: %w
Error message
failed to parse network CIDR %q: %w
What it means
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.
Source
Thrown at pkg/nodemodel/nodeupconfigbuilder.go:394
config.Packages = append(config.Packages, cluster.Spec.Packages...)
config.Packages = append(config.Packages, ig.Spec.Packages...)
return config, bootConfig, nil
}
// selectControlPlaneIPs narrows the addresses that reach the API server down to the ones a node
// in this cluster can actually connect to. Some of the addresses may be FQDNs or public IPs.
func selectControlPlaneIPs(cluster *kops.Cluster, apiserverAddresses []string) ([]string, error) {
var controlPlaneIPs []string
switch cluster.GetCloudProvider() {
case kops.CloudProviderAWS, kops.CloudProviderHetzner, kops.CloudProviderOpenstack:
// 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)
for _, additionalIP := range apiserverAddresses {
for _, networkCIDR := range append(cluster.Spec.Networking.AdditionalNetworkCIDRs, cluster.Spec.Networking.NetworkCIDR) {
cidr, err := netip.ParsePrefix(networkCIDR)
if err != nil {
return nil, fmt.Errorf("failed to parse network CIDR %q: %w", networkCIDR, err)
}
ip, err := netip.ParseAddr(additionalIP)
if err != nil {
continue
}
// Nodes in an IPv6-only cluster sit in subnets that have no IPv4 CIDR, so an IPv4
// address is unroutable from them even though it is inside the network CIDR. Handing
// one out only stalls bootstrap on an address that can never answer.
if cluster.Spec.IsIPv6Only() && !ip.Is6() {
continue
}
if cidr.Contains(ip) || ip.Is6() {
controlPlaneIPs = append(controlPlaneIPs, additionalIP)
}
}
}
case kops.CloudProviderGCE:View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before (cluster.yaml) networking: networkCIDR: 10.0.0.0 // after networking: networkCIDR: 10.0.0.0/16
Defensive patterns
Strategy: validation
Validate before calling
import "net/netip"
func validateNetworkCIDRs(networking kops.ClusterNetworkingSpec) error {
for _, cidr := range append(networking.AdditionalNetworkCIDRs, networking.NetworkCIDR) {
if _, err := netip.ParsePrefix(cidr); err != nil {
return fmt.Errorf("invalid network CIDR %q: %w", cidr, err)
}
}
return nil
} Type guard
func isValidCIDR(s string) bool {
_, err := netip.ParsePrefix(s)
return s != "" && err == nil
} Try / catch
ips, err := selectControlPlaneIPs(cluster, apiserverAddresses)
if err != nil {
var perr *net.ParseError
if errors.As(err, &perr) {
// malformed CIDR in cluster spec: surface spec field + value
return fmt.Errorf("cluster networking spec has invalid CIDR: %w", err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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'.
Common situations: 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.
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
- failed to parse subnet CIDR %q: %w
- unable to convert CIDR subnet new bits to int: %q: %v
- unable to convert CIDR subnet net num to int: %q: %v
- error populating configuration: %v
- unexpected IP address type for ServiceClusterIPRange: %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/72cbfe744eb6a23f.
Report an issue: GitHub.