{"record":{"id":"c8656b6204b441fa","repo":"shadowsocks/shadowsocks-rust","slug":"resolve-empty","errorCode":null,"errorMessage":"resolve empty","messagePattern":"resolve empty","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/shadowsocks-service/src/local/dns/dns_resolver.rs","lineNumber":53,"sourceCode":"            connect_opts: ConnectOpts::default(),\n            attempts: 2,\n        }\n    }\n\n    pub fn set_mode(&mut self, mode: Mode) {\n        self.mode = mode;\n    }\n\n    pub fn set_ipv6_first(&mut self, ipv6_first: bool) {\n        self.ipv6_first = ipv6_first;\n    }\n\n    pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) {\n        self.connect_opts = connect_opts;\n    }\n\n    async fn lookup(&self, msg: Message) -> io::Result<Message> {\n        let mut last_err = io::Error::new(ErrorKind::InvalidData, \"resolve empty\");\n\n        for _ in 0..self.attempts {\n            match self.lookup_inner(msg.clone()).await {\n                Ok(m) => return Ok(m),\n                Err(err) => last_err = err,\n            }\n        }\n\n        Err(last_err)\n    }\n\n    async fn lookup_inner(&self, msg: Message) -> io::Result<Message> {\n        match self.ns {\n            NameServerAddr::SocketAddr(ns) => {\n                let mut last_err = io::Error::new(ErrorKind::InvalidData, \"resolve empty\");\n\n                // Query UDP then TCP\n                if self.mode.enable_udp() {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/dns/dns_resolver.rs#L35-L71","documentation":"In the local DNS resolver service, lookup() retries lookup_inner up to `attempts` times and, if every attempt fails, returns the last error. When no attempts succeed at all, the initial placeholder io::Error \"resolve empty\" (InvalidData) is returned — meaning the resolver could not obtain any DNS response from the configured nameserver.","triggerScenarios":"Calling DnsResolver::resolve/lookup when the configured nameserver is unreachable, all UDP/TCP query attempts fail or time out, and `attempts` iterations all return Err so last_err stays the initial placeholder.","commonSituations":"DNS server address misconfigured or firewalled; local resolver down; no network connectivity; connect_opts (e.g. outbound interface) pointing at a broken path.","solutions":["Verify the configured DNS nameserver address is reachable (test with dig/nslookup against it)","Check network connectivity and firewall rules for UDP/TCP port 53 to the resolver","Increase the `attempts`/timeout settings in the local DNS server config if responses are slow","Check connect_opts — binding to the wrong interface or proxy path breaks queries"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: ensure the nameserver answers before relying on the resolver\n// dig +time=2 +tries=1 @<ns> example.com","typeGuard":null,"tryCatchPattern":"match resolver.resolve(addr, port).await {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains(\"resolve empty\") => {\n        // fall back to system resolver or retry after checking connectivity\n    }\n    r => r?,\n}","preventionTips":["Monitor nameserver reachability from the host","Set reasonable attempts/timeout in the local DNS config","Verify connect_opts (bind interface/proxy) match the deployment environment"],"tags":["dns","network","resolution","timeout"],"backgroundTag":"empty-result-set","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}