crowdsecurity/crowdsec · error
invalid IP '%s' for bot entry '%s' in %s: %w
Error message
invalid IP '%s' for bot entry '%s' in %s: %w
What it means
botFileInit parses each element of the entry's "ips" array with netip.ParseAddr and stores it in an in-memory set. This error is thrown when a listed IP is not a valid textual IP address (IPv4 or IPv6). The wrapped error is the netip.ParseAddr parse failure, and the message identifies the bad value, entry, and file.
Source
Thrown at pkg/exprhelpers/botfile.go:88
return fmt.Errorf("invalid user_agent regex for bot entry '%s' in %s: %w", entry.Name, filename, err)
}
}
for _, p := range entry.Paths {
re, err := compileBotRegex(p)
if err != nil {
return fmt.Errorf("invalid path regex '%s' for bot entry '%s' in %s: %w", p, entry.Name, filename, err)
}
entry.pathRegexes = append(entry.pathRegexes, re)
}
entry.ipSet = make(map[netip.Addr]struct{}, len(entry.IPs))
for _, ip := range entry.IPs {
addr, err := netip.ParseAddr(ip)
if err != nil {
return fmt.Errorf("invalid IP '%s' for bot entry '%s' in %s: %w", ip, entry.Name, filename, err)
}
entry.ipSet[addr.Unmap()] = struct{}{}
}
for _, r := range entry.Ranges {
prefix, err := netip.ParsePrefix(r)
if err != nil {
return fmt.Errorf("invalid CIDR range '%s' for bot entry '%s' in %s: %w", r, entry.Name, filename, err)
}
entry.prefixes = append(entry.prefixes, prefix.Masked())
}
for _, p := range entry.RDNS {
// an empty pattern matches every PTR-confirmed host: almost
// certainly a mistake, reject it
if p == "" {View on GitHub (pinned to 909b515798)
Solutions
- Fix the malformed value to a bare IPv4/IPv6 address, e.g. "192.0.2.10" or "2001:db8::1".
- If the value is a network like "1.2.3.0/24", move it to the "ranges" array — ParseAddr rejects CIDR notation.
- If it is a hostname, resolve it to an address or drop it; this loader does no DNS resolution for ips.
- Strip whitespace/BOM/quotes from each element; verify with `python3 -c "import ipaddress; ipaddress.ip_address('VALUE')"` or similar.
- Remove empty strings from the ips array.
Example fix
// before
{"name":"badbot","ips":["203.0.113.0/24","203.0.113.256"]}
// after
{"name":"badbot","ips":[],"ranges":["203.0.113.0/24"]} Defensive patterns
Strategy: validation
Validate before calling
for _, ip := range entry.IPs {
if _, err := netip.ParseAddr(strings.TrimSpace(ip)); err != nil {
// reject before FileInit
}
}
valid := err == nil Try / catch
if err := exprhelpers.FileInit(botFile, "bots"); err != nil {
var perr *net.ParseError
if strings.Contains(err.Error(), "invalid IP") {
log.Errorf("bad ips element: %v", err)
}
_ = perr
return err
} Prevention
- Keep single addresses in ips and networks in ranges — never mix.
- Trim whitespace and strip quotes when generating entries from external lists.
- Validate each element with netip.ParseAddr (or ipaddress.ip_address) in CI.
- Reject hostnames at ingestion time; resolve them upstream if needed.
When it happens
Trigger: A bots JSONL entry contains "ips":[...] with a malformed element: a CIDR like "1.2.3.0/24" (belongs in ranges), a hostname, "1.2.3.256", an empty string, or an address with a zone like "fe80::1%eth0".
Common situations: Putting CIDR ranges into "ips" instead of "ranges"; copy-pasting hostnames from a blocklist meant for DNS resolution; trailing whitespace or invisible characters; octet overflow typos; export scripts writing placeholder values like "<ip>".
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
- missing mandatory 'name' field in %s: %s
- bot entry '%s' in %s has no identity verification (need at l
- invalid user_agent regex for bot entry '%s' in %s: %w
- invalid path regex '%s' for bot entry '%s' in %s: %w
- empty rdns pattern for bot entry '%s' in %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/d37b6182a1c81a25.
Report an issue: GitHub.