lionsoul2014/ip2region · error

parse ip %s: %w

Error message

parse ip %s: %w

What it means

Go xdb.Searcher.Search: the string ip failed ParseIP, so it is neither a valid IPv4 nor IPv6 literal; the input string and the underlying parse error are wrapped together.

Source

Thrown at binding/golang/xdb/searcher.go:118

// IPVersion return the ip version
func (s *Searcher) IPVersion() *Version {
	return s.version
}

// GetIOCount return the global io count for the last search
func (s *Searcher) GetIOCount() int {
	return s.ioCount
}

// Search the region for the specified string or bytes ip address
func (s *Searcher) Search(ip any) (string, error) {
	var err error
	var ipBytes []byte
	switch v := ip.(type) {
	case string:
		ipBytes, err = ParseIP(v)
		if err != nil {
			return "", fmt.Errorf("parse ip %s: %w", v, err)
		}
	case []byte:
		ipBytes = v
	default:
		return "", fmt.Errorf("invalid ip value type %s", v)
	}

	// ip version check
	if len(ipBytes) != s.version.Bytes {
		return "", fmt.Errorf("invalid ip address(%s expected)", s.version.Name)
	}

	// reset the global ioCount
	s.ioCount = 0

	// locate the segment index block based on the vector index
	var il0, il1 = int(ipBytes[0]), int(ipBytes[1])
	var idx = il0*VectorIndexCols*VectorIndexSize + il1*VectorIndexSize

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Validate the IP string with net.ParseIP (or xdb.IsIPv4/IsIPv6) before calling Search.
  2. Trim whitespace and strip any port suffix from the input string.
  3. Check that the string family (v4 vs v6) matches the xdb file version the searcher was loaded for.
  4. Handle the wrapped error by inspecting err.Unwrap() to distinguish parse failure from read failure.

Example fix

// before
region, err := searcher.Search(ctx, rawIP)
// after
if net.ParseIP(strings.TrimSpace(rawIP)) == nil {
    return "", fmt.Errorf("not an IP: %q", rawIP)
}
region, err := searcher.Search(ctx, strings.TrimSpace(rawIP))
Defensive patterns

Strategy: validation

Validate before calling

ip := net.ParseIP(strings.TrimSpace(raw))
if ip == nil {
    return fmt.Errorf("invalid ip string: %q", raw)
}

Type guard

func isIPString(s string) bool { return net.ParseIP(strings.TrimSpace(s)) != nil }

Try / catch

region, err := searcher.Search(ctx, raw)
if err != nil {
    var parseErr error
    if errors.Unwrap(err) != nil { parseErr = errors.Unwrap(err) }
    return fmt.Errorf("lookup failed: %w (input=%q)", parseErr, raw)
}

Prevention

When it happens

Trigger: Calling searcher.Search(ctx, "999.1.2.3") or any malformed string like "abc", "1.2.3", or an IPv6 literal with bad syntax; also passing a v4-only string to a v6 searcher if ParseIP rejects it.

Common situations: Log-line IP fields containing placeholders like "-" or "unknown"; user-supplied input not validated before lookup; trailing whitespace or port appended ("1.2.3.4:8080").

Related errors


AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02). Data as JSON: /api/errors/9dcbf3c85935e810. Report an issue: GitHub.