shadowsocks/shadowsocks-rust · error
initialize DNS resolver with config failed, error: {}
Error message
initialize DNS resolver with config failed, error: {} What it means
create_resolver builds a hickory-dns (trust-dns) resolver from explicit name-server config; when builder.build() fails (e.g. no valid name servers after filtering, invalid configuration), the error is logged and re-wrapped as io::ErrorKind::Other. Message text is "initialize DNS resolver with config failed, error: {inner}".
Source
Thrown at crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs:164
if let Some(opts) = opts {
*builder.options_mut() = opts;
}
let resolver_opts = builder.options_mut();
// Use Ipv4AndIpv6 strategy. Because Ipv4ThenIpv6 or Ipv6ThenIpv4 will return if the first query returned.
// Since we want to use Happy Eyeballs to connect to both IPv4 and IPv6 addresses, we need both A and AAAA records.
resolver_opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;
// Enable EDNS0 for large records
resolver_opts.edns0 = true;
trace!("initializing DNS resolver with opts {:?}", resolver_opts);
match builder.build() {
Ok(resolver) => Ok(resolver),
Err(err) => {
error!("initialize DNS resolver with config failed, error: {}", err);
Err(io::Error::new(io::ErrorKind::Other, err))
}
}
}
// To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration
// Android doesn't have /etc/resolv.conf.
None => {
match DnsResolver::builder(ShadowDnsRuntimeProvider::new(connect_opts)) {
Ok(mut builder) => {
let opts = builder.options_mut();
// NOTE: timeout will be set by config (for example, /etc/resolv.conf on UNIX-like system)
//
// Only ip_strategy should be changed. Why Ipv4AndIpv6? See comments above.
opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;
// Enable EDNS0 for large records
opts.edns0 = true;
View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Check the inner error in the log line to see the underlying hickory failure
- Ensure at least one valid, reachable nameserver IP:port is present in the DNS config
- Fix malformed nameserver entries (valid IPs, port 53/853) in the configuration
- Enable system-config resolution instead of manual config if /etc/resolv.conf or OS settings are usable
Example fix
// before ns: ["999.999.1.1:53"] // after ns: ["8.8.8.8:53", "1.1.1.1:53"]
Defensive patterns
Strategy: fallback
Validate before calling
let ns: Vec<_> = cfg.nameservers.iter().filter(|n| n.parse::<std::net::SocketAddr>().is_ok()).collect();
if ns.is_empty() { return Err(anyhow!("no valid nameservers configured")); } Try / catch
match create_resolver(opts).await {
Err(e) if e.kind() == io::ErrorKind::Other => {
log::error!("resolver init failed: {e}; falling back to public DNS");
create_resolver_with_fallback_dns().await?
}
other => other?,
} Prevention
- Validate nameserver IPs/ports at config load
- Keep at least one known-good fallback resolver (e.g. 8.8.8.8)
- Read the logged inner error — it names the exact hickory build failure
When it happens
Trigger: Calling hickory_resolver / hickory_dns_system_resolver / hickory_dns_notify_update_dns where the explicitly provided nameserver config (ips, ports, trust anchors, opts) fails hickory's build validation — commonly zero usable name servers or invalid server addresses.
Common situations: Config file with malformed or empty nameservers list; all nameservers filtered out (e.g. IPv6 servers on IPv4-only host); invalid DNS port or bogus IP strings in dns config.
Related errors
- missing `local_dns_addr` or `remote_dns_addr` in configurati
- `local_dns_address` invalid
- invalid `dns` value, can only be [(tcp|udp)://]host[:port][,
- resolve empty
- resolve empty
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/7b49302a421871cf.
Report an issue: GitHub.