{"record":{"id":"0e6ada99bbb90587","repo":"shadowsocks/shadowsocks-rust","slug":"resolve-empty-0e6ada","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/server.rs","lineNumber":852,"sourceCode":"                }\n                decision = &mut decider, if !use_remote => {\n                    if let Some(local_response) = decision {\n                        trace!(\"pick local response (response): {:?}\", local_response);\n                        return (local_response, false);\n                    } else if let Some(remote_response) = remote_response {\n                        trace!(\"pick remote response (response): {:?}\", remote_response);\n                        return (remote_response, true);\n                    } else {\n                        use_remote = true;\n                    }\n                }\n                else => unreachable!(),\n            }\n        }\n    }\n\n    async fn lookup_remote(&self, query: &Query, remote_addr: &Address) -> 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_remote_inner(query, remote_addr).await {\n                Ok(m) => {\n                    return Ok(m);\n                }\n                Err(err) => last_err = err,\n            }\n        }\n\n        Err(last_err)\n    }\n\n    async fn lookup_remote_inner(&self, query: &Query, remote_addr: &Address) -> io::Result<Message> {\n        let mut message = Message::query();\n        message.metadata.recursion_desired = true;\n        message.add_query(query.clone());\n","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/dns/server.rs#L834-L870","documentation":"In the local DNS server's remote (ACL-routed) lookup path, lookup_remote retries lookup_remote_inner up to `attempts` times; if all attempts fail, the initial \"resolve empty\" placeholder io::Error is returned to acl_lookup. It indicates the remote DNS upstream never produced a usable response.","triggerScenarios":"acl_lookup routes a query to the remote path and every attempt of lookup_remote_inner (querying remote nameservers, possibly through the proxy) returns Err.","commonSituations":"Remote/upstream DNS unreachable through the proxy; proxy connection broken; upstream times out; remote nameserver address wrong in config.","solutions":["Check that the proxy/remote path to the upstream DNS is working (test general connectivity through the proxy)","Verify remote DNS server configuration and reachability","Increase attempts/timeout settings","Review logs for the inner per-attempt error to find the root cause"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight remote path: query upstream through the proxy before serving DNS\n// shadowsocks clients should confirm proxy connectivity first","typeGuard":null,"tryCatchPattern":"match server.acl_lookup(query, local).await {\n    Err(e) if e.to_string().contains(\"resolve empty\") => {\n        // remote upstream unreachable via proxy; retry or answer SERVFAIL\n    }\n    r => r,\n}","preventionTips":["Verify the proxy tunnel to remote DNS works during health checks","Increase attempts for slow remote paths","Monitor remote upstream latency and failures"],"tags":["dns","proxy","upstream","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"}