kubernetes/kops · error
unable to calculate CIDR mask size for %q: %q
Error message
unable to calculate CIDR mask size for %q: %q
What it means
After successfully parsing the prefix, CIDRSubnet calls baseCIDR.Mask.Size() to obtain the existing mask size and total address bits. Both are 0 only when the mask size cannot be determined (effectively an unusable mask), so the function refuses to proceed with this error.
Source
Thrown at upup/pkg/fi/utils/net.go:112
if err != nil {
return 0, 0, fmt.Errorf("unable to convert CIDR subnet net num to int: %q: %v", s[2], err)
}
return newSize, netNum, nil
}
// CIDRSubnet calculates a subnet address within given IP network address prefix.
// Inspired by the Terraform implementation of the "cidrsubnet" function
// https://www.terraform.io/docs/language/functions/cidrsubnet.html
func CIDRSubnet(prefix string, newSize int, netNum int64) (string, error) {
_, baseCIDR, err := net.ParseCIDR(prefix)
if err != nil {
return "", fmt.Errorf("unable to parse CIDR for %q: %v", prefix, err)
}
oldSize, totalSize := baseCIDR.Mask.Size()
if oldSize == 0 && totalSize == 0 {
return "", fmt.Errorf("unable to calculate CIDR mask size for %q: %q", prefix, baseCIDR.Mask)
}
newNetwork, err := cidr.SubnetBig(baseCIDR, newSize-oldSize, big.NewInt(netNum))
if err != nil {
return "", fmt.Errorf("unable to calculate subnet CIDR for %q -> /%d#%d : %v", prefix, newSize, netNum, err)
}
return newNetwork.String(), nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Replace the prefix with a canonical, well-formed CIDR (e.g. "10.0.0.0/16") and retry.
- Re-derive the CIDR from the cluster spec rather than from the corrupted value.
- Log the offending prefix and mask for debugging, then fix the upstream source of the value.
- Add a pre-call sanity check that a parsed CIDR's Mask.Size() returns a non-zero oldSize.
Example fix
// before
subnet, err := utils.CIDRSubnet(corruptedPrefix, 8, 1) // corrupted/undeterminable mask
// after
subnet, err := utils.CIDRSubnet("172.20.0.0/16", 8, 1) Defensive patterns
Strategy: validation
Validate before calling
func hasSizableMask(prefix string) bool {
_, cidrNet, err := net.ParseCIDR(prefix)
if err != nil {
return false
}
old, total := cidrNet.Mask.Size()
return old != 0 || total != 0
} Prevention
- Use canonical CIDR strings from known-good sources (kops-generated specs) rather than hand-mangled values.
- Sanity-check Mask.Size() output when ingesting CIDRs from untrusted tooling.
- Log the prefix and parsed mask when validation fails to speed diagnosis.
When it happens
Trigger: Calling CIDRSubnet with a prefix that parses but whose mask has no determinable size — practically rare, but reachable when the parsed CIDR carries a degenerate/invalid mask (e.g. through custom parsing paths or corrupted input that still satisfies net.ParseCIDR).
Common situations: Corrupted or programmatically mangled CIDR strings in cluster config; intermediate tooling rewriting networkCIDR into a form Go's parser accepts but whose mask is meaningless; fuzzed or adversarial input to the validation path.
Related errors
- failed to parse subnet CIDR %q: %w
- unable to parse CIDR for %q: %v
- unable to calculate subnet CIDR for %q -> /%d#%d : %v
- linode VPC requires at least one subnet
- linode subnet %q requires a CIDR
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/36ed4157344f44db.
Report an issue: GitHub.