XTLS/Xray-core · error

not an IP address:{}

Error message

not an IP address:{}

What it means

Returned by NameServerConfig.Build in infra/conf/dns.go when the per-server 'clientIp' field parses to a domain rather than an IP. Family().IsIP() is false for domains, so Xray rejects it with the offending value appended — DNS client IP must be a literal IPv4/IPv6 address.

Source

Thrown at infra/conf/dns.go:131

		} else {
			newUnexpectedIPs = append(newUnexpectedIPs, s)
		}
	}

	expectedIPRules, err := geodata.ParseIPRules(newExpectedIPs)
	if err != nil {
		return nil, err
	}

	unexpectedIPRules, err := geodata.ParseIPRules(newUnexpectedIPs)
	if err != nil {
		return nil, err
	}

	var myClientIP []byte
	if c.ClientIP != nil {
		if !c.ClientIP.Family().IsIP() {
			return nil, errors.New("not an IP address:", c.ClientIP.String())
		}
		myClientIP = []byte(c.ClientIP.IP())
	}

	return &dns.NameServer{
		Address: &net.Endpoint{
			Network: net.Network_UDP,
			Address: c.Address.Build(),
			Port:    uint32(c.Port),
		},
		ClientIp:        myClientIP,
		SkipFallback:    c.SkipFallback,
		Domain:          domainRules,
		ExpectedIp:      expectedIPRules,
		QueryStrategy:   resolveQueryStrategy(c.QueryStrategy),
		ActPrior:        actPrior,
		Tag:             c.Tag,
		TimeoutMs:       c.TimeoutMs,

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set clientIp to a local literal IP: "clientIp": "192.168.1.10"
  2. Put server hostnames in 'address', never in 'clientIp'
  3. Omit clientIp entirely if you do not need to pin the query source

Example fix

// before
{"address": "1.1.1.1", "clientIp": "myhost.example.com"}

// after
{"address": "1.1.1.1", "clientIp": "192.168.1.10"}
Defensive patterns

Strategy: type-guard

Validate before calling

func isLiteralIP(s string) bool {
    return net.ParseIP(s) != nil
}

Type guard

func isClientIPValid(v any) bool {
    s, ok := v.(string)
    return ok && net.ParseIP(s) != nil
}

Try / catch

if _, err := nsc.Build(); err != nil {
    if strings.Contains(err.Error(), "not an IP address") {
        return fmt.Errorf("clientIp %s must be a literal IP, not a domain", nsc.ClientIP)
    }
    return err
}

Prevention

When it happens

Trigger: {"address": "1.1.1.1", "clientIp": "example.com"} or clientIp set to an env: name resolving to a hostname. The string unmarshals fine (no error at parse time); failure happens only at Build.

Common situations: Confusing clientIp (source address for DNS queries) with the DNS server address; putting the server hostname in clientIp; env var pointing at a DDNS name.

Related errors


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