{"record":{"id":"8489e74d10cdc915","repo":"crowdsecurity/crowdsec","slug":"converting-first-ip-in-range-w","errorCode":null,"errorMessage":"converting first ip in range: %w","messagePattern":"converting first ip in range: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/types/ip.go","lineNumber":64,"sourceCode":"\n\tip := net.ParseIP(anyIP)\n\tif ip == nil {\n\t\treturn -1, 0, 0, 0, 0, fmt.Errorf(\"invalid ip address '%s'\", anyIP)\n\t}\n\n\tsz, start, end, err := IP2Ints(ip)\n\tif err != nil {\n\t\treturn -1, 0, 0, 0, 0, fmt.Errorf(\"invalid ip address '%s': %w\", anyIP, err)\n\t}\n\n\treturn sz, start, end, start, end, nil\n}\n\n/*size (16|4), nw_start, suffix_start, nw_end, suffix_end, error*/\nfunc Range2Ints(network net.IPNet) (int, int64, int64, int64, int64, error) {\n\tszStart, nwStart, sfxStart, err := IP2Ints(network.IP)\n\tif err != nil {\n\t\treturn -1, 0, 0, 0, 0, fmt.Errorf(\"converting first ip in range: %w\", err)\n\t}\n\n\tlastAddr := LastAddress(network)\n\n\tszEnd, nwEnd, sfxEnd, err := IP2Ints(lastAddr)\n\tif err != nil {\n\t\treturn -1, 0, 0, 0, 0, fmt.Errorf(\"transforming last address of range: %w\", err)\n\t}\n\n\tif szEnd != szStart {\n\t\treturn -1, 0, 0, 0, 0, fmt.Errorf(\"inconsistent size for range first(%d) and last(%d) ip\", szStart, szEnd)\n\t}\n\n\treturn szStart, nwStart, sfxStart, nwEnd, sfxEnd, nil\n}\n\nfunc uint2int(u uint64) int64 {\n\tvar ret int64","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/types/ip.go#L46-L82","documentation":"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).","triggerScenarios":"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().","commonSituations":"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.","solutions":["Validate the net.IPNet before calling: ensure network.IP != nil and network.IP.To16() != nil","Parse CIDR strings with net.ParseCIDR before calling Range2Ints so IP and Mask are consistent","Inspect the wrapped error to see the unexpected IP length and fix the source that produced the IP","Return/report the original input string so the user knows which value is malformed"],"exampleFix":"// before\nnet2 := net.IPNet{Mask: net.CIDRMask(24, 32)} // IP is nil\n_, _, _, _, _, err := types.Range2Ints(net2)\n// after\n_, ipnet, err := net.ParseCIDR(\"192.168.1.0/24\")\nif err != nil { return err }\n_, _, _, _, _, err := types.Range2Ints(*ipnet)","handlingStrategy":"validation","validationCode":"func validRange(n net.IPNet) bool { return n.IP != nil && n.IP.To16() != nil && n.Mask != nil }","typeGuard":"func isParsableIP(ip net.IP) bool { return ip != nil && ip.To16() != nil }","tryCatchPattern":null,"preventionTips":["Always build net.IPNet via net.ParseCIDR, never struct literals","Validate IPs at the config-parsing boundary","Test both IPv4 and IPv6 inputs"],"tags":["ip","parsing","cidr","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}