crowdsecurity/crowdsec · error

invalid ip address '%s': %w

Error message

invalid ip address '%s': %w

What it means

After net.ParseIP succeeds, Addr2Ints converts the address to integers via IP2Ints; if that conversion fails the error is wrapped as "invalid ip address '%s': %w". This indicates a parseable-looking address whose internal conversion failed — rare, typically an unexpected address representation rather than user error.

Source

Thrown at pkg/types/ip.go:54

/*returns a range for any ip or range*/
func Addr2Ints(anyIP string) (int, int64, int64, int64, int64, error) {
	if strings.Contains(anyIP, "/") {
		_, net, err := net.ParseCIDR(anyIP)
		if err != nil {
			return -1, 0, 0, 0, 0, fmt.Errorf("invalid ip range '%s': %w", anyIP, err)
		}

		return Range2Ints(*net)
	}

	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)
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Inspect the wrapped error from IP2Ints to see the conversion failure and normalize the input (e.g. ip.String() round-trip) before retrying
  2. Normalize the address with net.ParseIP(s).String() to canonical form before calling Addr2Ints
  3. Ensure the address is a well-formed textual IPv4/IPv6 (not a zone-suffixed or binary form)
  4. If it comes from an external feed, validate/parse at ingestion and reject malformed records early

Example fix

// before
r, err := types.NewRange(rawInput)
// after
canonical := net.ParseIP(strings.TrimSpace(rawInput))
if canonical == nil { return fmt.Errorf("not an ip: %s", rawInput) }
r, err := types.NewRange(canonical.String())
Defensive patterns

Strategy: validation

Validate before calling

import "net"
func canonicalIP(s string) (string, error) {
  ip := net.ParseIP(strings.TrimSpace(s))
  if ip == nil { return "", fmt.Errorf("not an ip: %q", s) }
  return ip.String(), nil
}

Try / catch

r, err := types.NewRange(input)
if err != nil {
  if strings.Contains(err.Error(), "invalid ip address") {
    if canon, cerr := canonicalIP(input); cerr == nil {
      r, err = types.NewRange(canon)
    }
    if err != nil { return err }
  } else { return err }
}

Prevention

When it happens

Trigger: IP2Ints(ip) returning an error for a parsed address — e.g. an IP form that does not convert to 4 or 16 bytes as expected — during Addr2Ints/NewRange.

Common situations: Programmatically constructed net.IP values or unusual textual forms slipping through; upstream data feed delivering addresses that parse but do not convert cleanly; version-dependent ParseIP acceptance changes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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