XTLS/Xray-core · error
failed to parse name server: {}
Error message
failed to parse name server: {} What it means
Thrown by NameServerConfig.UnmarshalJSON in infra/conf/dns.go when the 'servers' entry is neither a plain address string nor a valid advanced nameserver object (the object form with address/subnet settings failed to unmarshal or validate). The raw JSON data is appended to the message.
Source
Thrown at infra/conf/dns.go:81
c.Address = advanced.Address
c.ClientIP = advanced.ClientIP
c.Port = advanced.Port
c.SkipFallback = advanced.SkipFallback
c.Domains = advanced.Domains
c.ExpectedIPs = advanced.ExpectedIPs
c.ExpectIPs = advanced.ExpectIPs
c.QueryStrategy = advanced.QueryStrategy
c.Tag = advanced.Tag
c.TimeoutMs = advanced.TimeoutMs
c.DisableCache = advanced.DisableCache
c.ServeStale = advanced.ServeStale
c.ServeExpiredTTL = advanced.ServeExpiredTTL
c.FinalQuery = advanced.FinalQuery
c.UnexpectedIPs = advanced.UnexpectedIPs
return nil
}
return errors.New("failed to parse name server: ", string(data))
}
func (c *NameServerConfig) Build() (*dns.NameServer, error) {
if c.Address == nil {
return nil, errors.New("nameserver address is not specified")
}
domainRules, err := geodata.ParseDomainRules(c.Domains, geodata.Domain_Substr)
if err != nil {
return nil, err
}
if len(c.ExpectedIPs) == 0 {
c.ExpectedIPs = c.ExpectIPs
}
actPrior := false
var newExpectedIPs StringListView on GitHub (pinned to 7d214f8b09)
Solutions
- Use quoted strings: "servers": ["1.1.1.1", "8.8.8.8"]
- For object form always include a string address: {"address": "https://dns.google/dns-query", "domains": ["geosite:google"]}
- Check the appended raw data to find the failing entry
Example fix
// before
"servers": [{"adress": "1.1.1.1"}]
// after
"servers": [{"address": "1.1.1.1"}] Defensive patterns
Strategy: validation
Validate before calling
func validateDNSServerEntry(v any) error {
switch t := v.(type) {
case string:
if t == "" {
return errors.New("empty nameserver string")
}
return nil
case map[string]any:
addr, ok := t["address"]
if !ok {
return errors.New("nameserver object missing 'address' key")
}
_, isStr := addr.(string)
if !isStr {
return errors.New("nameserver 'address' must be a string")
}
return nil
}
return errors.New("nameserver must be a string or object with string address")
} Type guard
func isDNSServerEntry(v any) bool {
if _, ok := v.(string); ok {
return true
}
m, ok := v.(map[string]any)
return ok && reflect.TypeOf(m["address"]).Kind() == reflect.String
} Try / catch
if err := json.Unmarshal(entry, &nsc); err != nil {
if strings.Contains(err.Error(), "failed to parse name server") {
return fmt.Errorf("dns.servers entry %s: use a quoted string or {"address": "..."}", entry)
}
return err
} Prevention
- Quote DNS server addresses
- Object-form entries must contain a string 'address' key
- Lint the servers array before deploying
When it happens
Trigger: dns.servers entries like 8.8.8.8 (unquoted, invalid JSON or number), {"address": 123}, {"address": null}, an array ["a","b"] where one entry is a nested object, or an object missing a string 'address' field so the advanced-form branch fails.
Common situations: Mixing old-style string servers and new object form in one array incorrectly; forgetting quotes around DNS IPs with dots (usually a JSON syntax error caught earlier); typos in object keys so the address field stays empty.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- nameserver address is not specified
- not an IP address:{}
- invalid address
- invalid DNS hosts
- unknown action: {}
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/200ca896df30a0e6.
Report an issue: GitHub.