XTLS/Xray-core · error
failed to create hosts
Error message
failed to create hosts
What it means
After selecting a target length, writePaddingTurnWithBuffer computes recordLength = targetLength - prefixLength and requires it to be at least 1, because a padding record must contain its varint header plus payload. This error means the selected variant's total length (or a send-range draw) is not larger than the prefix that was already sent inside it, leaving no room for a record.
Source
Thrown at app/dns/dns.go:86
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)
updateRules := func(isLocalNameServer bool) {
// Prioritize local domains with specific TLDs or those without any dot for the local DNS
if isLocalNameServer {
effectiveRules = append(effectiveRules, localTLDsAndDotlessDomainsRules...)
for _, rule := range localTLDsAndDotlessDomainsRules {View on GitHub (pinned to 7d214f8b09)
Solutions
- Ensure every selectable variant/send-range draw is strictly longer than prefixLength
- For turn 0, keep minLength (and every variant total) >= firstTurnPrefixLength + 1
- Route writes through runPaddingSchedule so the up-front bounds check catches the misconfiguration deterministically
Example fix
// before: variant total 64 with prefix 64 leaves no record
paddingVariant{chunks: []int{64}}
// after
paddingVariant{chunks: []int{64, 256}} Defensive patterns
Strategy: validation
Validate before calling
minSelectable := turn.minLength
if len(turn.variants) > 0 {
minSelectable = math.MaxInt
for _, v := range turn.variants {
if l := paddingVariantLength(v); l < minSelectable {
minSelectable = l
}
}
}
if minSelectable-prefixLength < 1 {
return errors.New("turn cannot fit prefix plus a record")
} Prevention
- Keep every variant total and the send range strictly greater than the prefix
- Validate via runPaddingSchedule instead of calling write APIs directly
When it happens
Trigger: A variant on turn 0 whose chunk sum <= firstTurnPrefixLength, or a sendMinLength/sendMaxLength draw <= prefixLength. Note validation only guarantees minLength - prefix >= 1 for turn 0, so send-range draws below minLength (impossible after validation) or unvalidated direct writes trigger this.
Common situations: Calling writePaddingTurn directly with a short variant and a large prefix; a schedule where a variant equals the prefix length exactly; test scaffolding that passes prefixLength larger than the turn's target length.
Related errors
- Failed to convert address to Net IP.
- FakeDNSEngine is not initialized, but such a sniffer is used
- invalid fakeDNS setting
- tries to resolve itself!
- not a Service.
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/70b0646b5300aa07.
Report an issue: GitHub.