shadowsocks/shadowsocks-rust · error
dns
Error message
dns
What it means
This panic fires from `.expect("dns")` on `config.set_dns_formatted(dns)` when the value of the `--dns` CLI flag cannot be parsed as a DNS server specification. The library expects a formatted string like `"1.1.1.1","8.8.8.8:53,udp"` (address with optional port and protocol) and panics rather than returning an error for malformed input.
Source
Thrown at src/service/server.rs:467
#[cfg(all(unix, not(target_os = "android")))]
match matches.get_one::<u64>("NOFILE") {
Some(nofile) => config.nofile = Some(*nofile),
None => {
if config.nofile.is_none() {
crate::sys::adjust_nofile();
}
}
}
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
- Use a valid formatted DNS string, e.g. `--dns '"1.1.1.1"'` or `--dns '"8.8.8.8:53,udp"'` with proper shell quoting.
- Prefer IP addresses over hostnames in the --dns value.
- Verify shell quoting so commas and embedded double-quotes survive to the process.
- Remove --dns to use the system DNS resolution defaults.
- When modifying code, replace `.expect("dns")` with proper error propagation into ShadowsocksError.
Example fix
// before (shell eats the quotes -> malformed) ssserver --dns "1.1.1.1" // after ssserver --dns '"1.1.1.1"' # or with protocol ssserver --dns '"8.8.8.8:53,udp"'
Defensive patterns
Strategy: validation
Validate before calling
// Validate --dns before launching: quoted address, optional :port, optional ,udp|,tcp suffix
let dns = std::env::args().nth(/* position of --dns value */ 0).unwrap_or_default();
assert!(dns.starts_with('"') && dns.ends_with('"'), "--dns must be a quoted spec like \"8.8.8.8:53,udp\""); Type guard
fn looks_like_dns_spec(s: &str) -> bool {
let inner = s.trim().trim_matches('"');
inner.parse::<std::net::IpAddr>().is_ok()
|| inner.split_once(':').map(|(ip, _)| ip.parse::<std::net::IpAddr>().is_ok()).unwrap_or(false)
} Prevention
- Always single-quote --dns values in shell so embedded double quotes survive.
- Use IP addresses, not hostnames, in DNS specs.
- Follow the documented format: "addr" or "addr:port,proto" entries.
When it happens
Trigger: Running the server with `--dns` set to a malformed value, e.g. a bare hostname (`--dns dns.google`), an empty string, a value with wrong quoting/comma syntax, or an unsupported protocol suffix (`--dns "1.1.1.1,xxx"`).
Common situations: Copy-pasted DNS configs losing their quotes in shell escaping, using a hostname instead of an IP, missing the `,udp`/`,tcp` suffix rules, or shell stripping quotes so the parser sees a single malformed token.
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
- `password` is required for server {svr_addr}
- failed to create ServerConfig, error: {}
- missing local_dns_addr
- missing remote_dns_addr
- dns
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/9005aea96d8b9000.
Report an issue: GitHub.