shadowsocks/shadowsocks-rust · error
dns
Error message
dns
What it means
The manager service passes the `--dns` CLI value to `config.set_dns_formatted(dns).expect("dns")`. The panic means the DNS configuration string is malformed. `set_dns_formatted` accepts either a simple DNS server address (e.g. `8.8.8.8` / `[::1]:53`) or a JSON-formatted DNS config object, and rejects anything it cannot parse.
Source
Thrown at src/service/manager.rs:426
&& let Some(ref mut m) = config.manager
{
m.mode = Mode::UdpOnly;
}
if matches.get_flag("TCP_AND_UDP")
&& let Some(ref mut m) = config.manager
{
m.mode = Mode::TcpAndUdp;
}
if let Some(acl_file) = matches.get_one::<String>("ACL") {
let acl = AccessControl::load_from_file(acl_file)
.map_err(|err| ShadowsocksError::LoadAclFailure(format!("loading ACL \"{acl_file}\", {err}")))?;
config.acl = Some(acl);
}
if let Some(dns) = matches.get_one::<String>("DNS") {
config.set_dns_formatted(dns).expect("dns");
}
if let Some(dns_cache_size) = matches.get_one::<usize>("DNS_CACHE_SIZE") {
config.dns_cache_size = Some(*dns_cache_size);
}
if matches.get_flag("IPV6_FIRST") {
config.ipv6_first = true;
}
if let Some(udp_timeout) = matches.get_one::<u64>("UDP_TIMEOUT") {
config.udp_timeout = Some(Duration::from_secs(*udp_timeout));
}
if let Some(udp_max_assoc) = matches.get_one::<usize>("UDP_MAX_ASSOCIATIONS") {
config.udp_max_associations = Some(*udp_max_assoc);
}
View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Pass a plain nameserver like `--dns 8.8.8.8` or `--dns "1.1.1.1:53"`
- If using the JSON form, validate it with `jq` first: ensure it matches shadowsocks Config dns format
- Quote the whole JSON value properly for your shell
- Move complex DNS config into the config file instead of the CLI flag
Example fix
// before --dns "dns://8.8.8.8" // after --dns "8.8.8.8:53"
Defensive patterns
Strategy: validation
Validate before calling
use std::net::ToSocketAddrs;
fn valid_dns_value(v: &str) -> bool {
v.to_socket_addrs().is_ok() || serde_json::from_str::<serde_json::Value>(v).is_ok()
} Type guard
null
Try / catch
// mirror the library call with error reporting
if let Err(e) = config.set_dns_formatted(dns) {
eprintln!("invalid --dns value {dns:?}: {e}");
std::process::exit(2);
} Prevention
- Prefer plain nameserver addresses on the CLI
- Validate JSON DNS configs with jq before passing them
- Do not use dns:// URLs or resolv.conf paths with --dns
When it happens
Trigger: Passing `--dns` with a value that is neither a valid nameserver address (missing port with unparseable format, bad IP) nor valid JSON DNS config (malformed `"[\"8.8.8.8\", ...]"`-style strings, wrong keys).
Common situations: Hand-writing JSON DNS configs with quoting mistakes on the shell, using `dns://` URLs or resolv.conf paths which this API doesn't accept, typos in IP addresses.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid `dns` value, can only be [(tcp|udp)://]host[:port][,
- dns
- missing `local_dns_addr` or `remote_dns_addr` in configurati
- `local_dns_address` invalid
- method
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/508f91d664c31f25.
Report an issue: GitHub.