XTLS/Xray-core · error
invalid fakedns config
Error message
invalid fakedns config
What it means
Thrown by FakeDNSConfig.UnmarshalJSON when the fakedns JSON value matches neither a single pool object nor an array of pool objects. Xray accepts fakedns either as one {ipPool, lruSize} object or as a list of such objects; anything else (a string, number, or object with wrong shape that fails both unmarshal attempts) yields this error at JSON parse time, not Build time.
Source
Thrown at infra/conf/fakedns.go:45
return json.Marshal(f.pool)
} else if f.pools != nil {
return json.Marshal(f.pools)
}
}
return nil, errors.New("unexpected config state")
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error {
var pool FakeDNSPoolElementConfig
var pools []*FakeDNSPoolElementConfig
switch {
case json.Unmarshal(data, &pool) == nil:
f.pool = &pool
case json.Unmarshal(data, &pools) == nil:
f.pools = pools
default:
return errors.New("invalid fakedns config")
}
return nil
}
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})View on GitHub (pinned to 7d214f8b09)
Solutions
- Use the object form: {"ipPool": "198.18.0.0/15", "lruSize": 65535} or the array form [{...}, {...}].
- Replace old bare-CIDR fakedns strings with the pool object.
- Ensure field types are string/int respectively; unknown keys are ignored but wrong types are not.
- Run `xray run -test -c config.json` to catch it before starting the service.
Example fix
// before
"fakedns": "198.18.0.0/15"
// after
"fakedns": {"ipPool": "198.18.0.0/15", "lruSize": 65535} Defensive patterns
Strategy: validation
Validate before calling
function isFakeDNSPool(o) {
return o && typeof o === 'object' &&
(typeof o.ipPool === 'string' || typeof o.lruSize === 'number');
}
function isFakeDNSConfig(v) {
return isFakeDNSPool(v) || (Array.isArray(v) && v.every(isFakeDNSPool));
}
if (!isFakeDNSConfig(cfg.dns?.fakedns)) throw new Error('fakedns must be a pool object or array of pools'); Type guard
function isFakeDNSPool(o: unknown): o is { ipPool?: string; lruSize?: number } {
return typeof o === 'object' && o !== null &&
(o as any).ipPool === undefined || typeof (o as any).ipPool === 'string';
} Prevention
- Use the documented pool object shape ({ipPool, lruSize}) or arrays thereof.
- Replace legacy bare-CIDR fakedns strings when upgrading Xray.
- Validate config JSON against a JSON schema before loading.
When it happens
Trigger: "fakedns": "1.2.3.4/24" (old pre-pool syntax), "fakedns": {"ipPool": 123} (wrong field types), or "fakedns": 42. json.Unmarshal into FakeDNSPoolElementConfig and into []*FakeDNSPoolElementConfig both fail, hitting the default branch.
Common situations: Upgrading from very old Xray/V2Ray configs where fakedns took a bare CIDR string; typos in field names (e.g. "ippool" vs "ipPool") making the strict unmarshal fail when types mismatch; nesting pools one level too deep.
Related errors
- bridge tag is empty
- bridge domain is empty
- portal tag is empty
- portal domain is empty
- unknown format of a string list:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/8a046bfbaff84b17.
Report an issue: GitHub.