shadowsocks/shadowsocks-rust · error · io::Error
resolve empty
Error message
resolve empty
What it means
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.
Source
Thrown at crates/shadowsocks-service/src/local/dns/dns_resolver.rs:53
connect_opts: ConnectOpts::default(),
attempts: 2,
}
}
pub fn set_mode(&mut self, mode: Mode) {
self.mode = mode;
}
pub fn set_ipv6_first(&mut self, ipv6_first: bool) {
self.ipv6_first = ipv6_first;
}
pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) {
self.connect_opts = connect_opts;
}
async fn lookup(&self, msg: Message) -> io::Result<Message> {
let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");
for _ in 0..self.attempts {
match self.lookup_inner(msg.clone()).await {
Ok(m) => return Ok(m),
Err(err) => last_err = err,
}
}
Err(last_err)
}
async fn lookup_inner(&self, msg: Message) -> io::Result<Message> {
match self.ns {
NameServerAddr::SocketAddr(ns) => {
let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");
// Query UDP then TCP
if self.mode.enable_udp() {View on GitHub (pinned to 8eb0f0a65b)
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
Defensive patterns
Strategy: retry
Validate before calling
// preflight: ensure the nameserver answers before relying on the resolver // dig +time=2 +tries=1 @<ns> example.com
Try / catch
match resolver.resolve(addr, port).await {
Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains("resolve empty") => {
// fall back to system resolver or retry after checking connectivity
}
r => r?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: DNS server address misconfigured or firewalled; local resolver down; no network connectivity; connect_opts (e.g. outbound interface) pointing at a broken path.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- resolve empty
- unexpected response from 8.8.8.8:53
- redir destination must not be an domain name address
- tun destination must not be an domain name address
- initialize DNS resolver with system-config failed, error: {}
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/c8656b6204b441fa.
Report an issue: GitHub.