XTLS/Xray-core · error
tries to resolve itself!
Error message
tries to resolve itself!
What it means
In selectPaddingVariant, after randomly choosing an entry from turn.sendVariants (or the implicit all-indices list), the referenced variant index must satisfy 0 <= index < len(turn.variants). An out-of-range entry means sendVariants contains an index pointing at a variant that does not exist. paddingTurnBounds performs the same check during validation, so hitting this at runtime implies the write path was entered without prior validation (e.g. direct writePaddingTurn calls) or schedules were mutated after validation.
Source
Thrown at app/dns/nameserver_doh.go:140
}
func (s *DoHNameServer) newReqID() uint16 {
return 0
}
// getCacheController implements CachedNameserver.
func (s *DoHNameServer) getCacheController() *CacheController {
return s.cacheController
}
// sendQuery implements CachedNameserver.
func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
errors.LogInfo(ctx, s.Name(), " querying: ", fqdn)
if s.Name()+"." == "DOH//"+fqdn {
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead")
if noResponseErrCh != nil {
err := errors.New("tries to resolve itself!", s.Name())
if option.IPv4Enable {
noResponseErrCh <- err
}
if option.IPv6Enable {
noResponseErrCh <- err
}
}
return
}
// As we don't want our traffic pattern looks like DoH, we use Random-Length Padding instead of Block-Length Padding recommended in RFC 8467
// Although DoH server like 1.1.1.1 will pad the response to Block-Length 468, at least it is better than no padding for response at all
reqs, err := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, int(crypto.RandBetween(100, 300))))
if err != nil {
errors.LogErrorInner(ctx, err, "failed to build dns query for ", fqdn)
if noResponseErrCh != nil {
if option.IPv4Enable {
noResponseErrCh <- errView on GitHub (pinned to 7d214f8b09)
Solutions
- Ensure every sendVariants entry is within [0, len(variants)-1]
- Prefer omitting sendVariants entirely (all variants are then selectable safely)
- Run validatePaddingSchedule before writing so the bad index is reported deterministically with context
Example fix
// before
variants: []paddingVariant{v0, v1},
sendVariants: []int{0, 2},
// after
variants: []paddingVariant{v0, v1},
sendVariants: []int{0, 1}, Defensive patterns
Strategy: validation
Validate before calling
for _, idx := range turn.sendVariants {
if idx < 0 || idx >= len(turn.variants) {
return fmt.Errorf("send variant index %d out of range", idx)
}
} Prevention
- Omit sendVariants unless subset selection is truly needed
- Compute indices symbolically (named constants) instead of raw literals
- Validate the schedule before writing so the bad index fails deterministically
When it happens
Trigger: A paddingTurn with sendVariants like [3] while variants has 2 entries, written via writePaddingTurn directly; or schedule slices shared and mutated between validation and the write loop.
Common situations: Custom code composing turns programmatically with off-by-one indices; negative indices from unchecked config parsing; refactoring a variant list without updating the sendVariants index list.
Related errors
- Failed to convert address to Net IP.
- failed to create hosts
- invalid fakeDNS setting
- not a Service.
- Dispatcher: Invalid destination.
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/2f519003b13f7256.
Report an issue: GitHub.