crowdsecurity/crowdsec · error

inconsistent size for range first(%d) and last(%d) ip

Error message

inconsistent size for range first(%d) and last(%d) ip

What it means

Range2Ints requires the first and last addresses of the range to have the same size class (4 for IPv4, 16 for IPv6). If IP2Ints returns different sizes for the network base and the broadcast address, this error is thrown. It signals a net.IPNet whose IP and Mask encode inconsistent families, so the range cannot be represented as a uniform integer span.

Source

Thrown at pkg/types/ip.go:75

	return sz, start, end, start, end, nil
}

/*size (16|4), nw_start, suffix_start, nw_end, suffix_end, error*/
func Range2Ints(network net.IPNet) (int, int64, int64, int64, int64, error) {
	szStart, nwStart, sfxStart, err := IP2Ints(network.IP)
	if err != nil {
		return -1, 0, 0, 0, 0, fmt.Errorf("converting first ip in range: %w", err)
	}

	lastAddr := LastAddress(network)

	szEnd, nwEnd, sfxEnd, err := IP2Ints(lastAddr)
	if err != nil {
		return -1, 0, 0, 0, 0, fmt.Errorf("transforming last address of range: %w", err)
	}

	if szEnd != szStart {
		return -1, 0, 0, 0, 0, fmt.Errorf("inconsistent size for range first(%d) and last(%d) ip", szStart, szEnd)
	}

	return szStart, nwStart, sfxStart, nwEnd, sfxEnd, nil
}

func uint2int(u uint64) int64 {
	var ret int64
	if u == math.MaxInt64 {
		ret = 0
	} else if u == math.MaxUint64 {
		ret = math.MaxInt64
	} else if u > math.MaxInt64 {
		u -= math.MaxInt64
		ret = int64(u)
	} else {
		ret = int64(u)
		ret -= math.MaxInt64
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Keep both endpoints in the same family: call network.IP.To4() and use a 4-byte mask for IPv4, To16()/CIDRMask(n,128) for IPv6
  2. Parse CIDRs with net.ParseCIDR rather than constructing net.IPNet manually
  3. Log the two sizes from the message to identify which field is the wrong family
  4. Reject such IPNet values at the configuration-parsing boundary before numeric conversion

Example fix

// before
ipnet := net.IPNet{IP: net.ParseIP("192.168.1.0").To4(), Mask: net.CIDRMask(24, 128)}
_, _, _, _, _, err := types.Range2Ints(ipnet) // inconsistent size 4 vs 16
// after
ipnet := net.IPNet{IP: net.ParseIP("192.168.1.0").To4(), Mask: net.CIDRMask(24, 32)}
Defensive patterns

Strategy: validation

Validate before calling

func sameFamilyEndpoints(n net.IPNet) bool {
    last := types.LastAddress(n)
    return (n.IP.To4() != nil) == (last.To4() != nil)
}

Type guard

func uniformFamily(n net.IPNet) bool { return n.IP.To4() != nil && types.LastAddress(n).To4() != nil || n.IP.To4() == nil }

Prevention

When it happens

Trigger: Range2Ints (or Addr2Ints with a CIDR) with a net.IPNet whose base IP normalizes to 4 bytes while the ORed host-mask address normalizes to 16 bytes (or vice versa) — i.e. mixed IPv4/IPv6 fields in one net.IPNet.

Common situations: Hand-built net.IPNet where IP is a 4-byte representation but the mask indexing produced a 16-byte result; code paths that convert only one endpoint with To4(); corrupted IPNet values from external data.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/7e614c12a2c09c87. Report an issue: GitHub.