{"record":{"id":"79261dd10b6f8b72","repo":"shadowsocks/shadowsocks-rust","slug":"dns","errorCode":null,"errorMessage":"dns","messagePattern":"dns","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/service/local.rs","lineNumber":900,"sourceCode":"\n        #[cfg(all(unix, not(target_os = \"android\")))]\n        match matches.get_one::<u64>(\"NOFILE\") {\n            Some(nofile) => config.nofile = Some(*nofile),\n            None => {\n                if config.nofile.is_none() {\n                    crate::sys::adjust_nofile();\n                }\n            }\n        }\n\n        if let Some(acl_file) = matches.get_one::<String>(\"ACL\") {\n            let acl = AccessControl::load_from_file(acl_file)\n                .map_err(|err| ShadowsocksError::LoadAclFailure(format!(\"loading ACL \\\"{acl_file}\\\", {err}\")))?;\n            config.acl = Some(acl);\n        }\n\n        if let Some(dns) = matches.get_one::<String>(\"DNS\") {\n            config.set_dns_formatted(dns).expect(\"dns\");\n        }\n\n        if let Some(dns_cache_size) = matches.get_one::<usize>(\"DNS_CACHE_SIZE\") {\n            config.dns_cache_size = Some(*dns_cache_size);\n        }\n\n        if matches.get_flag(\"IPV6_FIRST\") {\n            config.ipv6_first = true;\n        }\n\n        if let Some(udp_timeout) = matches.get_one::<u64>(\"UDP_TIMEOUT\") {\n            config.udp_timeout = Some(Duration::from_secs(*udp_timeout));\n        }\n\n        if let Some(udp_max_assoc) = matches.get_one::<usize>(\"UDP_MAX_ASSOCIATIONS\") {\n            config.udp_max_associations = Some(*udp_max_assoc);\n        }\n","sourceCodeStart":882,"sourceCodeEnd":918,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/src/service/local.rs#L882-L918","documentation":"The DNS value from --dns is passed to config.set_dns_formatted, which parses a comma/space-separated list of name servers (and optional protocol prefixes like udp://, tcp://, https://); malformed input makes the .expect(\"dns\") panic. This must run under the local-dns feature and accepts formats like 8.8.8.8 or 8.8.8.8:53.","triggerScenarios":"Running sslocal with --dns set to a malformed nameserver list: missing port with a bad token (\"8.8.8.8:dnsgarbage\"), empty entries (\"8.8.8.8,,1.1.1.1\"), unsupported scheme (ftp://8.8.8.8), or a value like \"systemd\" instead of a real address.","commonSituations":"Pasting resolv.conf-style content; using \"systemd-resolved\" as a value; extra whitespace/typos in addresses; scheme typos (htps://); trying \"local\" instead of an IP.","solutions":["Use a comma-separated list of valid name servers, e.g. --dns \"8.8.8.8,1.1.1.1\".","Prefix protocols explicitly when needed: \"udp://8.8.8.8:53,tcp://1.1.1.1:53,https://dns.google/dns-query\".","Pre-validate each token parses as a NameServerAddr (or fix scheme/port typos) before invoking."],"exampleFix":"// before\nsslocal --dns \"systemd-resolved\" ...\n\n// after\nsslocal --dns \"udp://127.0.0.53:53,8.8.8.8\" ...","handlingStrategy":"validation","validationCode":"fn validate_dns_arg(dns: &str) -> Result<(), String> {\n    for ns in dns.split(',').map(str::trim).filter(|s| !s.is_empty()) {\n        let ns = ns.strip_prefix(\"udp://\").or_else(|| ns.strip_prefix(\"tcp://\"))\n            .unwrap_or(ns);\n        if ns.parse::<std::net::SocketAddr>().is_err()\n            && ns.parse::<std::net::IpAddr>().is_err() {\n            return Err(format!(\"invalid dns nameserver: {}\", ns));\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"config.set_dns_formatted(dns).unwrap_or_else(|e| {\n    eprintln!(\"invalid --dns value '{}': {}\", dns, e);\n    std::process::exit(2);\n});","preventionTips":["Pass explicit IP[:port] nameservers, comma-separated: \"8.8.8.8,1.1.1.1\".","Use correct scheme prefixes (udp://, tcp://, https://) when non-default DNS is needed.","Never pass resolver names like \"systemd-resolved\"; use its listener IP 127.0.0.53 instead."],"tags":["cli","rust","dns","config","panic"],"backgroundTag":"invalid-config-value","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"}