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
- 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.
- If writing Go code against the API, check len(rules) > 0 before calling the matcher constructor and return nil matcher instead.
- 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
- Never emit an empty "ip": [] array in routing rules — omit the key instead.
- Add a config lint step rejecting empty arrays for matcher fields.
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
- failed to check code
- balancing strategy returns empty tag
- empty domain rule list
- unknown domain type:
- failed to open
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/bd0f9a72c293af1d.
Report an issue: GitHub.