XTLS/Xray-core · error
failed to create expected ip matcher
Error message
failed to create expected ip matcher
What it means
On a range-based turn, readPaddingTurn requires the peer's total turn length to fall within [turn.minLength, turn.maxLength] (paddingTurnAcceptsLength). The received length is outside that window, meaning the two endpoints' length bounds for this turn disagree.
Source
Thrown at app/dns/nameserver.go:116
updateRules func(bool),
) (*Client, error) {
client := &Client{}
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// Create a new server for each client for now
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning()
}
_, isLocalDNS := server.(*LocalNameServer)
updateRules(isLocalDNS)
// Establish expected IPs
var expectedMatcher geodata.IPMatcher
if len(ns.ExpectedIp) > 0 {
expectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.ExpectedIp)
if err != nil {
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
}
}
// Establish unexpected IPs
var unexpectedMatcher geodata.IPMatcher
if len(ns.UnexpectedIp) > 0 {
unexpectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.UnexpectedIp)
if err != nil {
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
}
}
if len(clientIP) > 0 {
switch ns.Address.Address.GetAddress().(type) {
case *net.IPOrDomain_Domain:
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
case *net.IPOrDomain_Ip:
errors.LogInfo(ctx, "DNS: client ", net.IP(ns.Address.Address.GetIp()), " uses clientIP ", clientIP.String())View on GitHub (pinned to 7d214f8b09)
Solutions
- Set identical minLength/maxLength for each turn on both peers
- Ensure any sendMinLength/sendMaxLength on the sender is within the receiver's accept window for that turn
- Roll out schedule changes atomically to both endpoints
Example fix
// before: sender sends 100-2000, receiver accepts 100-1000
// receiver turn: {minLength: 100, maxLength: 1000}
// after
// receiver turn: {minLength: 100, maxLength: 2000} Defensive patterns
Strategy: validation
Validate before calling
func rangesOverlap(sender, receiver paddingTurn) bool {
lo, hi := sender.minLength, sender.maxLength
if sender.sendMinLength != 0 || sender.sendMaxLength != 0 {
lo, hi = sender.sendMinLength, sender.sendMaxLength
}
return lo >= receiver.minLength && hi <= receiver.maxLength
} Try / catch
if err != nil && strings.Contains(err.Error(), "is outside") {
// bounds skew: align minLength/maxLength on both peers, then reconnect
} Prevention
- Mirror the bounds of every receive turn onto the peer's send capability
- Roll out bound changes to both endpoints atomically
When it happens
Trigger: Sender's minLength/maxLength (or its send range draw) yields a length the receiver's [minLength, maxLength] does not cover; asymmetric configs where one side widened or narrowed the range; note the receiver checks its own bounds, not the sender's send range.
Common situations: Tuning padding bounds on the server but not clients; sending with a send range wider than the receiver's accept range (send range validation only checks it fits the sender's own bounds); version skew after config rollout.
Related errors
- Dispatcher: Invalid destination.
- failed to create nameserver
- not a Service.
- FakeDNSEngine is not initialized, but such a sniffer is used
- Failed to convert address to Net IP.
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/a6beb92a746ae444.
Report an issue: GitHub.