kubernetes/kops · error
unable to calculate subnet CIDR for %q -> /%d#%d : %v
Error message
unable to calculate subnet CIDR for %q -> /%d#%d : %v
What it means
CIDRSubnet delegates the actual subnet computation to cidr.SubnetBig(baseCIDR, newSize-oldSize, netNum). If the requested new-bit expansion is invalid — e.g. newSize is smaller than or equal to the existing prefix size, or the expansion exceeds the address space — SubnetBig fails and the error is wrapped with the prefix, newSize, and netNum for diagnosis.
Source
Thrown at upup/pkg/fi/utils/net.go:117
}
// 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
- Ensure newSize is greater than the base prefix size and within the address space (e.g. /16 base, newSize 24 is valid; 16 is not).
- Keep netNum within [0, 2^(newSize-oldSize)); e.g. for an 8-bit expansion, netNum must be 0-255.
- Check calculateSubnetCIDR inputs (zone index, subnet count) for out-of-range arithmetic.
- Compute the expansion bits explicitly and assert 0 < newSize-oldSize <= totalSize-oldSize before calling.
Example fix
// before
subnet, err := utils.CIDRSubnet("172.20.0.0/16", 8, 1) // newSize smaller than oldSize
// after
subnet, err := utils.CIDRSubnet("172.20.0.0/16", 24, 1) Defensive patterns
Strategy: validation
Validate before calling
func validSubnetRequest(prefix string, newSize int, netNum int64) error {
_, cidrNet, err := net.ParseCIDR(prefix)
if err != nil {
return err
}
old, total := cidrNet.Mask.Size()
if newSize <= old || newSize > total {
return fmt.Errorf("newSize /%d must satisfy /%d < /%d <= /%d", newSize, old, newSize, total)
}
maxNet := int64(1) << uint(newSize-old)
if netNum < 0 || netNum >= maxNet {
return fmt.Errorf("netNum %d out of range [0,%d)", netNum, maxNet)
}
return nil
} Prevention
- Assert newSize > existing prefix bits and within total address bits before expanding.
- Keep netnum below 2^(newSize-oldSize); compute zone-index based netnums defensively.
- Add table-driven tests covering edge sizes (newSize == oldSize, newSize == totalSize).
When it happens
Trigger: Calling CIDRSubnet with newSize <= oldSize of the prefix (e.g. requesting /8 inside a /16), or newSize so large the subnet bits exceed the address family's total bits, or a netNum outside the range of addressable subnets (via calculateSubnetCIDR).
Common situations: Mistyped subnet-mask constants in cluster spec; asking for a subnet smaller than the parent prefix; offset/netnum exceeding the number of available subnets; IPv4 config values accidentally used in the IPv6 expansion path.
Related errors
- failed to parse subnet CIDR %q: %w
- unable to parse CIDR for %q: %v
- unable to calculate CIDR mask size for %q: %q
- 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/718bb5ec29b324c0.
Report an issue: GitHub.