XTLS/Xray-core · error

no valid ip matcher

Error message

no valid ip matcher

What it means

Returned when building the heuristic IP matcher ends up with zero sub-matchers: the caller passed an empty (or fully-negated-away) list of IP rules. The switch on len(subs) hits case 0, meaning neither positive nor negative GeoIP rule lists produced any matcher.

Source

Thrown at common/geodata/ip_matcher.go:1013

	if len(posGeoip) > 0 {
		ipset, err := f.GetOrCreateFromGeoIPRules(posGeoip)
		if err != nil {
			return nil, err
		}
		subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false})
	}

	if len(negGeoip) > 0 {
		ipset, err := f.GetOrCreateFromGeoIPRules(negGeoip)
		if err != nil {
			return nil, err
		}
		subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: true})
	}

	switch len(subs) {
	case 0:
		return nil, errors.New("no valid ip matcher")
	case 1:
		return subs[0], nil
	default:
		return &HeuristicMultiIPMatcher{matchers: subs}, nil
	}
}

func newIPSetFactory() *IPSetFactory {
	return &IPSetFactory{shared: utils.NewWeakCacheMap[string, IPSet]()}
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Populate the rule's ip field with at least one valid entry (e.g. "geoip:private") or remove the empty ip array from the routing rule.
  2. If writing Go code against the API, check len(rules) > 0 before calling the matcher constructor and return nil matcher instead.
  3. Lint your config with `xray run -test` to catch empty arrays before runtime.

Example fix

// before
{ "type": "field", "ip": [], "outboundTag": "block" }

// after
{ "type": "field", "ip": ["geoip:private"], "outboundTag": "block" }
Defensive patterns

Strategy: validation

Validate before calling

if len(ipRules) == 0 {
    return nil, errors.New("refusing to build IP matcher: no rules supplied")
}

Try / catch

if m, err := newHeuristicIPMatcher(rules, negRules); err != nil {
    if strings.Contains(err.Error(), "no valid ip matcher") { /* skip IP matching for this rule */ }
}

Prevention

When it happens

Trigger: Constructing a router IP matcher from an empty []string of IP rules; passing only whitespace/malformed entries that were filtered out upstream; calling the builder programmatically with nil rules slice.

Common situations: JSON config where the routing rule's "ip" array is empty ([]), which Xray's JSON parser may pass through; programmatic API users building a Rule with no IP conditions and then forcing IP-matcher construction.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/bd0f9a72c293af1d. Report an issue: GitHub.