crowdsecurity/crowdsec · error

converting first ip in range: %w

Error message

converting first ip in range: %w

What it means

Range2Ints converts a net.IPNet range into integer bounds. Before doing anything else it converts the network's first address (network.IP) via IP2Ints; if that fails, the failure is wrapped with this message. It indicates the network's base IP is nil or has an unusable byte length (not 4 or 16 bytes).

Source

Thrown at pkg/types/ip.go:64

	ip := net.ParseIP(anyIP)
	if ip == nil {
		return -1, 0, 0, 0, 0, fmt.Errorf("invalid ip address '%s'", anyIP)
	}

	sz, start, end, err := IP2Ints(ip)
	if err != nil {
		return -1, 0, 0, 0, 0, fmt.Errorf("invalid ip address '%s': %w", anyIP, err)
	}

	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

View on GitHub (pinned to 909b515798)

Solutions

  1. Validate the net.IPNet before calling: ensure network.IP != nil and network.IP.To16() != nil
  2. Parse CIDR strings with net.ParseCIDR before calling Range2Ints so IP and Mask are consistent
  3. Inspect the wrapped error to see the unexpected IP length and fix the source that produced the IP
  4. Return/report the original input string so the user knows which value is malformed

Example fix

// before
net2 := net.IPNet{Mask: net.CIDRMask(24, 32)} // IP is nil
_, _, _, _, _, err := types.Range2Ints(net2)
// after
_, ipnet, err := net.ParseCIDR("192.168.1.0/24")
if err != nil { return err }
_, _, _, _, _, err := types.Range2Ints(*ipnet)
Defensive patterns

Strategy: validation

Validate before calling

func validRange(n net.IPNet) bool { return n.IP != nil && n.IP.To16() != nil && n.Mask != nil }

Type guard

func isParsableIP(ip net.IP) bool { return ip != nil && ip.To16() != nil }

Prevention

When it happens

Trigger: Calling Range2Ints (directly or via Addr2Ints on a CIDR string) with a net.IPNet whose IP field is nil or a zero-length/invalid net.IP — e.g. a hand-constructed net.IPNet{Mask: ...} without IP, or an IP that fails both To4() and To16().

Common situations: Building net.IPNet structs manually from config or untrusted input where the IP was never parsed; parsing malformed CIDR strings through custom code instead of net.ParseCIDR; storing IPs in a format that lost its bytes before calling this helper.

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/8489e74d10cdc915. Report an issue: GitHub.