XTLS/Xray-core · error
unexpected client IP length
Error message
unexpected client IP length
What it means
A padding schedule is an alternating dialogue: each turn must switch direction (client-to-server, then server-to-client, and so on). validatePaddingSchedule rejects two consecutive turns with the same direction, because both sides would simultaneously wait to read (deadlock) or both write (protocol desync).
Source
Thrown at app/dns/dns.go:49
domainMatcher geodata.DomainMatcher
matcherInfos []*DomainMatcherInfo
checkSystem bool
}
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher.
type DomainMatcherInfo struct {
clientIdx uint16
domainRule string
}
// New creates a new DNS server with given configuration.
func New(ctx context.Context, config *Config) (*DNS, error) {
var clientIP net.IP
switch len(config.ClientIp) {
case 0, net.IPv4len, net.IPv6len:
clientIP = net.IP(config.ClientIp)
default:
return nil, errors.New("unexpected client IP length ", len(config.ClientIp))
}
var ipOption dns.IPOption
checkSystem := false
switch config.QueryStrategy {
case QueryStrategy_USE_IP:
ipOption = dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}
case QueryStrategy_USE_SYS:
ipOption = dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}
checkSystem = trueView on GitHub (pinned to 7d214f8b09)
Solutions
- Flip the direction of turn i (or i-1) so consecutive turns alternate
- If both directions are genuinely needed back-to-back, merge the intent into one turn or insert a turn of the opposite direction between them
- Add a unit assertion over generated schedules that directions strictly alternate
Example fix
// before
[]paddingTurn{
{direction: paddingClientToServer, minLength: 100, maxLength: 200},
{direction: paddingClientToServer, minLength: 100, maxLength: 200},
}
// after
[]paddingTurn{
{direction: paddingClientToServer, minLength: 100, maxLength: 200},
{direction: paddingServerToClient, minLength: 100, maxLength: 200},
} Defensive patterns
Strategy: validation
Validate before calling
func directionsAlternate(s []paddingTurn) bool {
for i := 1; i < len(s); i++ {
if s[i].direction == s[i-1].direction {
return false
}
}
return true
} Prevention
- Generate schedules from a direction parameter that flips each iteration
- Unit-test alternation over every fixture schedule
When it happens
Trigger: schedule[i].direction == schedule[i-1].direction for any i > 0. Caught by validatePaddingSchedule at startup, before traffic.
Common situations: Inserting an extra client-to-server turn to add cover traffic without flipping the next turn's direction; generating schedules programmatically with a direction bug; hand-editing a copied schedule and dropping the alternation.
Related errors
- not a Service.
- Dispatcher: Invalid destination.
- FakeDNSEngine is not initialized, but such a sniffer is used
- Failed to convert address to Net IP.
- failed to create hosts
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/c65113a4973dc1ee.
Report an issue: GitHub.