XTLS/Xray-core · error
failed to create nameserver
Error message
failed to create nameserver
What it means
On a variants-based turn, readPaddingTurn accepts only total lengths equal to one of the configured variants (paddingTurnAcceptsLength compares against each variant's chunk sum). The peer's turn length matched none of them, so the schedules on the two sides disagree: the sender picked a variant the receiver does not know.
Source
Thrown at app/dns/nameserver.go:105
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
}
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
func NewClient(
ctx context.Context,
ns *NameServer,
clientIP net.IP,
disableCache bool, serveStale bool, serveExpiredTTL uint32,
tag string,
ipOption dns.IPOption,
updateRules func(bool),
) (*Client, error) {
client := &Client{}
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// Create a new server for each client for now
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning()
}
_, 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)View on GitHub (pinned to 7d214f8b09)
Solutions
- Copy the identical variants schedule to both peers (same chunk layouts in the same order)
- Version the schedule and negotiate/verify it at startup so mismatches fail loudly before traffic
- If variants differ intentionally per direction, ensure each side's receive turns list the variants the other side sends
Example fix
// before (client sends variant lengths 360/520; server only knows 360)
// server turn: variants [{100,260}]
// after (server lists both)
// server turn: variants [{100,260},{100,420}] Defensive patterns
Strategy: validation
Validate before calling
// before connecting, confirm the peer's advertised variant lengths are all known locally
func acceptsAll(peerLengths []int, localTurn paddingTurn) bool {
for _, l := range peerLengths {
if !paddingTurnAcceptsLength(localTurn, l) {
return false
}
}
return true
} Try / catch
if err != nil && strings.Contains(err.Error(), "not an allowed variant") {
// schedule skew between peers: re-sync configs, then reconnect
} Prevention
- Distribute one schedule file to both endpoints and pin its version
- Include a schedule hash in handshake metadata and fail fast on mismatch
- When changing variants, deploy both sides before enabling new traffic
When it happens
Trigger: Client and server configured with different variant lists (added/removed/reordered variants); peer using sendVariants indices that reference variants absent on this side; only reachable when len(turn.variants) > 0.
Common situations: Deploying a new variant set to one endpoint only; typos when duplicating variant JSON between client and server configs; independent 'obfuscation profile' files drifting apart.
Related errors
- Failed to convert address to Net IP.
- failed to create expected ip matcher
- 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/0519ccde2584ffb5.
Report an issue: GitHub.