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

  1. Replace the prefix with a canonical, well-formed CIDR (e.g. "10.0.0.0/16") and retry.
  2. Re-derive the CIDR from the cluster spec rather than from the corrupted value.
  3. Log the offending prefix and mask for debugging, then fix the upstream source of the value.
  4. 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

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


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