XTLS/Xray-core · error
unexpected query strategy
Error message
unexpected query strategy
What it means
While writing a padding turn, writePaddingTurnWithBuffer draws the turn's start delay via randomPaddingDelay(turn.startDelay); this error wraps that failure. Two sub-causes exist: the delay range is invalid (min < 0 or max < min), or crypto/rand.Int failed at the OS level. The invalid-range cause is normally caught earlier by validatePaddingSchedule, so in practice this surfaces when a lower-level write API is called on an unvalidated turn or the system entropy source errors.
Source
Thrown at app/dns/dns.go:81
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}
checkSystem = true
case QueryStrategy_USE_IP4:
ipOption = dns.IPOption{
IPv4Enable: true,
IPv6Enable: false,
FakeEnable: false,
}
case QueryStrategy_USE_IP6:
ipOption = dns.IPOption{
IPv4Enable: false,
IPv6Enable: true,
FakeEnable: false,
}
default:
return nil, errors.New("unexpected query strategy ", config.QueryStrategy)
}
hosts, err := NewStaticHosts(config.StaticHosts)
if err != nil {
return nil, errors.New("failed to create hosts").Base(err)
}
defaultTag := config.Tag
if len(config.Tag) == 0 {
defaultTag = generateRandomTag()
}
clients := make([]*Client, 0, len(config.NameServer))
matcherInfos := make([]*DomainMatcherInfo, 0)
effectiveRules := make([]*geodata.DomainRule, 0)
for _, ns := range config.NameServer {
clientIdx := len(clients)View on GitHub (pinned to 7d214f8b09)
Solutions
- Fix the delay range: min >= 0 and max >= min
- Prefer runPaddingSchedule over direct writePaddingTurn calls so validation runs first
- If caused by rand.Reader failure, check OS entropy availability (e.g. wait for the entropy source in minimal containers)
Example fix
// before
startDelay: paddingDelayRange{min: 50 * time.Millisecond, max: 10 * time.Millisecond}
// after
startDelay: paddingDelayRange{min: 10 * time.Millisecond, max: 50 * time.Millisecond} Defensive patterns
Strategy: validation
Validate before calling
func validDelay(d paddingDelayRange) bool {
return d.min >= 0 && d.max >= d.min
}
// check turn.startDelay and every variant delay before writing Try / catch
if err := writePaddingTurn(w, turn, prefix); err != nil {
if strings.Contains(err.Error(), "select padding start delay") {
// config bug in delay range or entropy failure; do not retry unchanged
}
return err
} Prevention
- Route turns through runPaddingSchedule for up-front delay validation
- Order delay bounds at config parse time (swap if min > max)
- Monitor rand.Reader health on entropy-poor hosts
When it happens
Trigger: Calling writePaddingTurn/writePaddingTurnWithSleep directly (bypassing runPaddingSchedule validation) with a malformed startDelay; or rand.Reader failing (entropy exhaustion, heavily restricted environments).
Common situations: Unit tests or custom transport code invoking the write path with hand-built turns; containers/VMs with depleted entropy at boot; a delay range built from config parsing that allows negative durations.
Related errors
- Unable to parse CIDR for Fake DNS IP assignment
- failed to create client
- not a Service.
- Dispatcher: Invalid destination.
- FakeDNSEngine is not initialized, but such a sniffer is used
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/85a426071e7b56b5.
Report an issue: GitHub.