XTLS/Xray-core · error
invalid DNS hosts
Error message
invalid DNS hosts
What it means
Thrown by HostsWrapper.UnmarshalJSON in infra/conf/dns.go when the dns.hosts value as a whole is not a JSON object mapping hostnames to HostAddress values. json.Unmarshal into map[string]*HostAddress must succeed; otherwise the error is returned with the json error chained via .Base(err).
Source
Thrown at infra/conf/dns.go:250
return &dns.Config_HostMapping{
Ip: ips,
}
}
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
func (m *HostsWrapper) MarshalJSON() ([]byte, error) {
return json.Marshal(m.Hosts)
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (m *HostsWrapper) UnmarshalJSON(data []byte) error {
hosts := make(map[string]*HostAddress)
err := json.Unmarshal(data, &hosts)
if err == nil {
m.Hosts = hosts
return nil
}
return errors.New("invalid DNS hosts").Base(err)
}
// Build implements Buildable
func (m *HostsWrapper) Build() ([]*dns.Config_HostMapping, error) {
mappings := make([]*dns.Config_HostMapping, 0, len(m.Hosts))
for rule, addrs := range m.Hosts {
mapping := newHostMapping(addrs)
rule, err := geodata.ParseDomainRule(rule, geodata.Domain_Full)
if err != nil {
return nil, err
}
mapping.Domain = rule
mappings = append(mappings, mapping)
}
return mappings, nil
}
// Build implements BuildableView on GitHub (pinned to 7d214f8b09)
Solutions
- Make hosts a flat object: "hosts": {"domain.example": "1.2.3.4"}
- Run the config through a JSON validator to catch structural syntax errors
- Inspect the chained base error for the exact JSON position
Example fix
// before
"hosts": ["example.com"]
// after
"hosts": {"example.com": "1.2.3.4"} Defensive patterns
Strategy: type-guard
Validate before calling
func validateHostsShape(v any) error {
m, ok := v.(map[string]any)
if !ok {
return errors.New("hosts must be an object mapping domains to addresses")
}
for k, val := range m {
if err := isHostAddressValue(val); err != nil {
return fmt.Errorf("hosts[%s]: %w", k, err)
}
}
return nil
} Type guard
func isHostsMap(v any) bool {
m, ok := v.(map[string]any)
if !ok {
return false
}
for _, val := range m {
if !isHostAddress(val) {
return false
}
}
return true
} Try / catch
if err := json.Unmarshal(data, &hw); err != nil {
if strings.Contains(err.Error(), "invalid DNS hosts") {
return fmt.Errorf("dns.hosts must be an object like {"example.com": "1.2.3.4"}")
}
return err
} Prevention
- hosts is a flat map, not an array
- Validate JSON structure with jq or a linter before loading
When it happens
Trigger: "hosts": ["example.com"], "hosts": "example.com", "hosts": 123, or a JSON object whose keys are fine but syntax errors exist (missing quotes, trailing comma) making the map unmarshal fail.
Common situations: Treating hosts like an array of domain strings; YAML-to-JSON converters emitting null for an empty hosts map in some edge cases; per-entry problems surface as error 254 instead, so this one indicates a structural (map-level) problem.
Related errors
- invalid address
- failed to parse name server: {}
- nameserver address is not specified
- not an IP address:{}
- failed to build hosts
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/f68879f5bf63e7ae.
Report an issue: GitHub.