{"record":{"id":"b6434d2b2615becf","repo":"XTLS/Xray-core","slug":"no-valid-fakedns-config","errorCode":null,"errorMessage":"no valid FakeDNS config","messagePattern":"no valid FakeDNS config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/fakedns.go","lineNumber":68,"sourceCode":"func (f *FakeDNSConfig) Build() (*fakedns.FakeDnsPoolMulti, error) {\n\tfakeDNSPool := fakedns.FakeDnsPoolMulti{}\n\n\tif f.pool != nil {\n\t\tfakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{\n\t\t\tIpPool:  f.pool.IPPool,\n\t\t\tLruSize: f.pool.LRUSize,\n\t\t})\n\t\treturn &fakeDNSPool, nil\n\t}\n\n\tif f.pools != nil {\n\t\tfor _, v := range f.pools {\n\t\t\tfakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{IpPool: v.IPPool, LruSize: v.LRUSize})\n\t\t}\n\t\treturn &fakeDNSPool, nil\n\t}\n\n\treturn nil, errors.New(\"no valid FakeDNS config\")\n}\n\ntype FakeDNSPostProcessingStage struct{}\n\nfunc (FakeDNSPostProcessingStage) Process(config *Config) error {\n\tfakeDNSInUse := false\n\tisIPv4Enable, isIPv6Enable := true, true\n\n\tif config.DNSConfig != nil {\n\t\tfor _, v := range config.DNSConfig.Servers {\n\t\t\tif v.Address.Family().IsDomain() && strings.EqualFold(v.Address.Domain(), \"fakedns\") {\n\t\t\t\tfakeDNSInUse = true\n\t\t\t}\n\t\t}\n\n\t\tswitch strings.ToLower(config.DNSConfig.QueryStrategy) {\n\t\tcase \"useip4\", \"useipv4\", \"use_ip4\", \"use_ipv4\", \"use_ip_v4\", \"use-ip4\", \"use-ipv4\", \"use-ip-v4\":\n\t\t\tisIPv4Enable, isIPv6Enable = true, false","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/fakedns.go#L50-L86","documentation":"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).","triggerScenarios":"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.","commonSituations":"Programmatic embedding of Xray as a library where the caller builds config structs by hand; reflection-based config assembly that skips the JSON stage.","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."],"exampleFix":"// before\nf := &conf.FakeDNSConfig{}\np, err := f.Build() // errors: no valid FakeDNS config\n\n// after\nf := &conf.FakeDNSConfig{}\n// populate via JSON unmarshal:\n_ = f.UnmarshalJSON([]byte(`{\"ipPool\":\"198.18.0.0/15\",\"lruSize\":65535}`))\np, err := f.Build()","handlingStrategy":"validation","validationCode":"if f.pool == nil && f.pools == nil {\n    return nil, errors.New(\"refusing to Build empty FakeDNSConfig\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always source FakeDNSConfig from JSON unmarshaling so the shape is normalized.","In library code, check pool/pools are set before calling Build()."],"tags":["go","xray","fakedns","config","api-misuse"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}