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

  1. Fix the malformed value to a bare IPv4/IPv6 address, e.g. "192.0.2.10" or "2001:db8::1".
  2. If the value is a network like "1.2.3.0/24", move it to the "ranges" array — ParseAddr rejects CIDR notation.
  3. If it is a hostname, resolve it to an address or drop it; this loader does no DNS resolution for ips.
  4. Strip whitespace/BOM/quotes from each element; verify with `python3 -c "import ipaddress; ipaddress.ip_address('VALUE')"` or similar.
  5. 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

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


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