kubernetes/kops · error
unable to convert CIDR subnet new bits to int: %q: %v
Error message
unable to convert CIDR subnet new bits to int: %q: %v
What it means
ParseCIDRNotation in upup/pkg/fi/utils/net.go parses expanded IPv6 CIDR notation strings of the form <prefix>:<newbits>:<netnum>. The middle segment (new bits) must be a valid decimal integer; when strconv.Atoi on that segment fails, this error is returned with the offending segment and the underlying strconv error.
Source
Thrown at upup/pkg/fi/utils/net.go:90
if ip.To4() != nil {
return false
}
return true
}
// ParseCIDRNotation parses a string in the format "/<newSize>#<netNum>"
// and returns the values of <newSize> and <netNum>.
func ParseCIDRNotation(subnet string) (int, int64, error) {
re := regexp.MustCompile(`^/(\d+)#([a-f0-9]+)$`)
s := re.FindStringSubmatch(subnet)
if len(s) != 3 {
return 0, 0, fmt.Errorf("unable to parse CIDR subnet string %q using %q", subnet, re)
}
newSize, err := strconv.Atoi(s[1])
if err != nil {
return 0, 0, fmt.Errorf("unable to convert CIDR subnet new bits to int: %q: %v", s[1], err)
}
netNum, err := strconv.ParseInt(s[2], 16, 64)
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)
}View on GitHub (pinned to 4c8573c808)
Solutions
- Fix the CIDR-subnet string so the middle segment is a valid decimal integer (e.g. "2001:db8:0000::/48:0:0" style <prefix>:<newbits>:<netnum>).
- Confirm the string matches the three-segment format expected by ParseCIDRNotation (regex splits into 3 parts separated by ':').
- Validate user/cluster-spec input before calling, e.g. with strconv.Atoi on the middle segment yourself to get a clearer message.
- Strip whitespace or stray characters (signs, units) from the segment before parsing.
Example fix
// before cidr := "2001:db8:0000::/48x:0" // '48x' is not an integer newSize, netNum, err := utils.ParseCIDRNotation(cidr) // after cidr := "2001:db8:0000::/48:0" newSize, netNum, err := utils.ParseCIDRNotation(cidr)
Defensive patterns
Strategy: validation
Validate before calling
func validNewBits(notation string) bool {
parts := strings.Split(notation, ":")
if len(parts) != 3 {
return false
}
_, err := strconv.Atoi(parts[1])
return err == nil
} Prevention
- Always build cidrsubnet-style notation programmatically with fmt.Sprintf("%s/%d:%d:%d", ...) instead of string concatenation by hand.
- Pre-validate the three segments with strconv.Atoi (base 10) and strconv.ParseInt (base 16) in tests.
- Add unit tests covering malformed middle segments for any config parsing that feeds ParseCIDRNotation.
When it happens
Trigger: Calling ParseCIDRNotation (directly or via validateIPv6CIDR, RenderTerraform, or calculateSubnetCIDR) with a CIDR-subnet string whose middle segment is not a decimal integer, e.g. an empty segment ("2001:db8::/32::0"), non-numeric text ("/32x:0"), or a segment with whitespace or signs.
Common situations: Hand-edited cluster spec or Terraform output where the cidrsubnet-style notation was malformed; copy/paste errors dropping a digit; templating that produced an empty middle segment; confusing the notation with standard CIDR syntax and writing a netmask instead of new-bits.
Related errors
- unable to convert CIDR subnet net num to int: %q: %v
- failed to parse network CIDR %q: %w
- unable to parse CIDR for %q: %v
- unexpected IP address type for ServiceClusterIPRange: %s
- failed to parse subnet CIDR %q: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/2455ba3cbc234161.
Report an issue: GitHub.