kubernetes/kops · error

unable to convert CIDR subnet net num to int: %q: %v

Error message

unable to convert CIDR subnet net num to int: %q: %v

What it means

ParseCIDRNotation parses the third segment of the expanded IPv6 CIDR-subnet notation as a base-16 (hex) integer (the subnet net number). When strconv.ParseInt(s, 16, 64) fails, this error wraps the strconv error with the offending segment.

Source

Thrown at upup/pkg/fi/utils/net.go:95

}

// 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)
	}

	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)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Correct the netnum segment to a valid hex value (0-9, a-f), e.g. "2001:db8:0000::/48:8:0".
  2. Remember the netnum is parsed in base 16 — supply hex, not decimal with invalid digits.
  3. Ensure the segment is non-empty and free of whitespace or stray characters.
  4. Pre-validate with strconv.ParseInt(segment, 16, 64) before calling to localize the problem.

Example fix

// before
cidr := "2001:db8:0000::/48:8:zz" // 'zz' is not hex
newSize, netNum, err := utils.ParseCIDRNotation(cidr)
// after
cidr := "2001:db8:0000::/48:8:ff"
newSize, netNum, err := utils.ParseCIDRNotation(cidr)
Defensive patterns

Strategy: validation

Validate before calling

func validNetNum(notation string) bool {
	parts := strings.Split(notation, ":")
	if len(parts) != 3 {
		return false
	}
	_, err := strconv.ParseInt(parts[2], 16, 64)
	return err == nil
}

Prevention

When it happens

Trigger: Calling ParseCIDRNotation (via validateIPv6CIDR, RenderTerraform, or calculateSubnetCIDR) with a third segment that is not valid hex, e.g. "2001:db8::/48:8:zz", a segment containing 'g'-'z', or an empty/whitespace netnum.

Common situations: Typos when hand-writing cidrsubnet-style IPv6 subnet notation; generating the notation from a template that emitted decimal or placeholder text for the netnum; copy/paste mangling hex digits.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/3dd9429a49b16983. Report an issue: GitHub.