XTLS/Xray-core · error
failed to create unexpected ip matcher
Error message
failed to create unexpected ip matcher
What it means
After the header and length checks pass, readPaddingTurn drains the padding body in 16 KiB reads via io.ReadFull; this error wraps that read failing. It means the connection died or truncated mid-turn: EOF/ErrUnexpectedEOF (peer closed before sending all padding bytes), reset, deadline exceeded, or read-side cancellation.
Source
Thrown at app/dns/nameserver.go:125
_, 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())
}
}
timeoutMs := 4000 * time.Millisecond
if ns.TimeoutMs > 0 {
timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond
}
checkSystem := ns.QueryStrategy == QueryStrategy_USE_SYSView on GitHub (pinned to 7d214f8b09)
Solutions
- Raise the connection read deadline above the sender's maximum total padding delay (start delay + sum of chunk delays)
- Classify via errors.Is(err, io.ErrUnexpectedEOF) etc. and reconnect - partial turns cannot be resumed
- Reduce configured delay ranges if intermediaries time out the padded stream
Example fix
// before conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) // after conn.SetReadDeadline(time.Now().Add(30 * time.Second))
Defensive patterns
Strategy: retry
Try / catch
if err := readPaddingTurn(r, turn, prefix); err != nil {
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) || os.IsTimeout(errors.Unwrap(err)) {
// truncated/dead turn: discard connection, reconnect with backoff
}
} Prevention
- Size read deadlines above the schedule's worst-case total delay
- Cap sender-side delay ranges below intermediary idle timeouts
- Never resume a partially read padding turn
When it happens
Trigger: Peer aborts after sending only part of its padding record; read deadline shorter than the peer's injected padding delays; middlebox cutting long padded bursts; TLS layer failing underneath.
Common situations: Aggressive chunk delays on the sender exceeding the receiver's read timeout; mobile networks dropping mid-handshake; LBs with per-read idle limits; sender crashing between chunks.
Related errors
- LRU size is bigger than subnet size
- No available name server could be created from
- read encryption request: %w
- not a Service.
- Dispatcher: Invalid destination.
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/fd2213c398fb822f.
Report an issue: GitHub.