XTLS/Xray-core · error
no valid FakeDNS config
Error message
no valid FakeDNS config
What it means
Thrown by FakeDNSConfig.Build() when neither the single-pool nor the multi-pool field was populated. Because UnmarshalJSON always sets one of f.pool/f.pools on success, this error in practice means Build() was called on a zero-value FakeDNSConfig that was never unmarshaled from JSON (or was constructed programmatically and left empty).
Source
Thrown at infra/conf/fakedns.go:68
func (f *FakeDNSConfig) Build() (*fakedns.FakeDnsPoolMulti, error) {
fakeDNSPool := fakedns.FakeDnsPoolMulti{}
if f.pool != nil {
fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{
IpPool: f.pool.IPPool,
LruSize: f.pool.LRUSize,
})
return &fakeDNSPool, nil
}
if f.pools != nil {
for _, v := range f.pools {
fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{IpPool: v.IPPool, LruSize: v.LRUSize})
}
return &fakeDNSPool, nil
}
return nil, errors.New("no valid FakeDNS config")
}
type FakeDNSPostProcessingStage struct{}
func (FakeDNSPostProcessingStage) Process(config *Config) error {
fakeDNSInUse := false
isIPv4Enable, isIPv6Enable := true, true
if config.DNSConfig != nil {
for _, v := range config.DNSConfig.Servers {
if v.Address.Family().IsDomain() && strings.EqualFold(v.Address.Domain(), "fakedns") {
fakeDNSInUse = true
}
}
switch strings.ToLower(config.DNSConfig.QueryStrategy) {
case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4":
isIPv4Enable, isIPv6Enable = true, falseView on GitHub (pinned to 7d214f8b09)
Solutions
- Populate at least one pool: set the pool field ({ipPool, lruSize}) or the pools slice before Build().
- Prefer loading fakedns config from JSON so UnmarshalJSON normalizes both shapes.
- Check for nil/zero FakeDNSConfig before calling Build() in library code.
Example fix
// before
f := &conf.FakeDNSConfig{}
p, err := f.Build() // errors: no valid FakeDNS config
// after
f := &conf.FakeDNSConfig{}
// populate via JSON unmarshal:
_ = f.UnmarshalJSON([]byte(`{"ipPool":"198.18.0.0/15","lruSize":65535}`))
p, err := f.Build() Defensive patterns
Strategy: validation
Validate before calling
if f.pool == nil && f.pools == nil {
return nil, errors.New("refusing to Build empty FakeDNSConfig")
} Prevention
- Always source FakeDNSConfig from JSON unmarshaling so the shape is normalized.
- In library code, check pool/pools are set before calling Build().
When it happens
Trigger: Constructing FakeDNSConfig{} directly in Go code and calling Build(); JSON-decoded configs are prevented from reaching this by the UnmarshalJSON error path. Also reachable if custom code sets neither pool nor pools.
Common situations: Programmatic embedding of Xray as a library where the caller builds config structs by hand; reflection-based config assembly that skips the JSON stage.
Related errors
- invalid fakedns config
- unknown type
- failed to get outbound handler with tag: ${tag}
- existing tag found: ${tag}
- bridge tag is empty
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/b6434d2b2615becf.
Report an issue: GitHub.