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, false

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Populate at least one pool: set the pool field ({ipPool, lruSize}) or the pools slice before Build().
  2. Prefer loading fakedns config from JSON so UnmarshalJSON normalizes both shapes.
  3. 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

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


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/b6434d2b2615becf. Report an issue: GitHub.