{"record":{"id":"789d969ff6a54e5f","repo":"XTLS/Xray-core","slug":"not-an-ip-address","errorCode":null,"errorMessage":"not an IP address:{}","messagePattern":"not an IP address:(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/dns.go","lineNumber":131,"sourceCode":"\t\t} else {\n\t\t\tnewUnexpectedIPs = append(newUnexpectedIPs, s)\n\t\t}\n\t}\n\n\texpectedIPRules, err := geodata.ParseIPRules(newExpectedIPs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tunexpectedIPRules, err := geodata.ParseIPRules(newUnexpectedIPs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar myClientIP []byte\n\tif c.ClientIP != nil {\n\t\tif !c.ClientIP.Family().IsIP() {\n\t\t\treturn nil, errors.New(\"not an IP address:\", c.ClientIP.String())\n\t\t}\n\t\tmyClientIP = []byte(c.ClientIP.IP())\n\t}\n\n\treturn &dns.NameServer{\n\t\tAddress: &net.Endpoint{\n\t\t\tNetwork: net.Network_UDP,\n\t\t\tAddress: c.Address.Build(),\n\t\t\tPort:    uint32(c.Port),\n\t\t},\n\t\tClientIp:        myClientIP,\n\t\tSkipFallback:    c.SkipFallback,\n\t\tDomain:          domainRules,\n\t\tExpectedIp:      expectedIPRules,\n\t\tQueryStrategy:   resolveQueryStrategy(c.QueryStrategy),\n\t\tActPrior:        actPrior,\n\t\tTag:             c.Tag,\n\t\tTimeoutMs:       c.TimeoutMs,","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/dns.go#L113-L149","documentation":"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.","triggerScenarios":"{\"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.","commonSituations":"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.","solutions":["Set clientIp to a local literal IP: \"clientIp\": \"192.168.1.10\"","Put server hostnames in 'address', never in 'clientIp'","Omit clientIp entirely if you do not need to pin the query source"],"exampleFix":"// before\n{\"address\": \"1.1.1.1\", \"clientIp\": \"myhost.example.com\"}\n\n// after\n{\"address\": \"1.1.1.1\", \"clientIp\": \"192.168.1.10\"}","handlingStrategy":"type-guard","validationCode":"func isLiteralIP(s string) bool {\n    return net.ParseIP(s) != nil\n}","typeGuard":"func isClientIPValid(v any) bool {\n    s, ok := v.(string)\n    return ok && net.ParseIP(s) != nil\n}","tryCatchPattern":"if _, err := nsc.Build(); err != nil {\n    if strings.Contains(err.Error(), \"not an IP address\") {\n        return fmt.Errorf(\"clientIp %s must be a literal IP, not a domain\", nsc.ClientIP)\n    }\n    return err\n}","preventionTips":["clientIp accepts only literal IPv4/IPv6","Hostnames belong in 'address', never 'clientIp'"],"tags":["config","dns","validation","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}