XTLS/Xray-core · error

invalid resolver + r

Error message

invalid resolver  + r

What it means

Thrown by Xdns.Build() for every entry in the 'resolvers' list that does not contain the '+udp://' marker. Resolvers must be encoded in a compound form like 'IP+udp://domain' — the +udp:// part selects UDP transport and carries the DNS name. Any other shape (bare IP, plain URL, tcp scheme) is rejected.

Source

Thrown at infra/conf/transport_finalmask.go:713

type Xdns struct {
	Domain json.RawMessage `json:"domain"`

	Domains   []string `json:"domains"`
	Resolvers []string `json:"resolvers"`
}

func (c *Xdns) Build() (proto.Message, error) {
	if c.Domain != nil {
		return nil, errors.PrintRemovedFeatureError("domain", "domains(server) & resolvers(client)")
	}

	if len(c.Domains) == 0 && len(c.Resolvers) == 0 {
		return nil, errors.New("empty domains & empty resolvers")
	}

	for _, r := range c.Resolvers {
		if !strings.Contains(r, "+udp://") {
			return nil, errors.New("invalid resolver ", r)
		}
	}

	return &xdns.Config{
		Domains:   c.Domains,
		Resolvers: c.Resolvers,
	}, nil
}

type XMC struct {
	Hostname string       `json:"hostname"`
	Profiles []XMCProfile `json:"profiles"`
	Password string       `json:"password"`
}

type XMCProfile struct {
	// Resolve the UUID by username, then request the session profile with
	// unsigned=false. Client and server must use the same signed profile.

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Rewrite each resolver as '<source-ip>+udp://<domain>', e.g. "1.1.1.1+udp://cloudflare-dns.com".
  2. Verify the '+' is present and the marker is exactly '+udp://'.
  3. If you only need domain routing, move entries to 'domains' instead.

Example fix

// before
"resolvers": ["8.8.8.8"]
// after
"resolvers": ["8.8.8.8+udp://dns.google"]
Defensive patterns

Strategy: validation

Validate before calling

for _, r := range resolvers {
    if !strings.Contains(r, "+udp://") {
        return fmt.Errorf("resolver %q must look like '<ip>+udp://<domain>'", r)
    }
}

Prevention

When it happens

Trigger: Writing "8.8.8.8" or "https://dns.google" or "1.1.1.1+tcp://example.com" in the resolvers array triggers this at Build(). Only strings containing '+udp://' pass, e.g. "1.1.1.1+udp://dns.google".

Common situations: Assuming resolvers take plain host:port DNS addresses; migrating from another client that accepts bare IPs; typos like 'udp://' without the '+' or '+udp:/'.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/f78775481a8078f5. Report an issue: GitHub.