{"record":{"id":"319d178d357f31ef","repo":"shadowsocks/shadowsocks-rust","slug":"missing-local-dns-addr","errorCode":null,"errorMessage":"missing local_dns_addr","messagePattern":"missing local_dns_addr","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/shadowsocks-service/src/local/mod.rs","lineNumber":411,"sourceCode":"                    server_builder.set_mode(local_config.mode);\n                    server_builder.set_tcp_redir(local_config.tcp_redir);\n                    server_builder.set_udp_redir(local_config.udp_redir);\n                    if let Some(udp_addr) = local_config.udp_addr {\n                        server_builder.set_udp_bind_addr(udp_addr);\n                    }\n\n                    let server = server_builder.build().await?;\n                    local_server.redir_servers.push(server);\n                }\n                #[cfg(feature = \"local-dns\")]\n                ProtocolType::Dns => {\n                    let client_addr = match local_config.addr {\n                        Some(a) => a,\n                        None => return Err(io::Error::other(\"dns requires local address\")),\n                    };\n\n                    let mut server_builder = {\n                        let local_addr = local_config.local_dns_addr.expect(\"missing local_dns_addr\");\n                        let remote_addr = local_config.remote_dns_addr.expect(\"missing remote_dns_addr\");\n                        let client_cache_size = local_config.client_cache_size.unwrap_or(5);\n\n                        DnsBuilder::with_context(\n                            context.clone(),\n                            client_addr,\n                            local_addr.clone(),\n                            remote_addr.clone(),\n                            balancer,\n                            client_cache_size,\n                        )\n                    };\n                    server_builder.set_mode(local_config.mode);\n\n                    #[cfg(target_os = \"macos\")]\n                    if let Some(n) = local_config.launchd_tcp_socket_name {\n                        server_builder.set_launchd_tcp_socket_name(n);\n                    }","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/mod.rs#L393-L429","documentation":"In DNS relay mode (protocol = \"dns\"), LocalConfig.local_dns_addr holds the address the local DNS resolver binds/uses. The builder expects it unconditionally (Option::expect) when constructing DnsBuilder, so a dns-mode config lacking local_dns_addr panics with \"missing local_dns_addr\". It is a programming/config invariant: dns mode cannot start without it.","triggerScenarios":"Configuring protocol = \"dns\" in the local server config without setting local_dns_addr (e.g. only remote_dns_addr provided), then calling LocalServer::new — the expect fires at construction time.","commonSituations":"Partial migration from a socks config to dns mode; hand-edited config dropping the field; generated configs not aware that dns mode needs both local_dns_addr and remote_dns_addr.","solutions":["Set local_dns_addr in the dns-mode local config, e.g. local_dns_addr = \"127.0.0.1:8053\"","Also verify remote_dns_addr is set (it is expected on the next line and would panic similarly)","Validate the config with shadowsocks' config validation before launch","Use a config schema/example from the docs for dns mode to ensure all required fields are present"],"exampleFix":"# before\nclass = \"local\"\nprotocol = \"dns\"\nlocal_address = \"127.0.0.1:1080\"\nremote_dns_addr = \"8.8.8.8:53\"\n# after\nclass = \"local\"\nprotocol = \"dns\"\nlocal_address = \"127.0.0.1:1080\"\nlocal_dns_addr = \"127.0.0.1:8053\"\nremote_dns_addr = \"8.8.8.8:53\"","handlingStrategy":"validation","validationCode":"if local_config.protocol == ProtocolType::Dns {\n    assert!(local_config.addr.is_some(), \"dns requires local address\");\n    assert!(local_config.local_dns_addr.is_some(), \"dns requires local_dns_addr\");\n}","typeGuard":"fn dns_config_ok(cfg: &LocalConfig) -> bool {\n    cfg.protocol != ProtocolType::Dns || (cfg.addr.is_some() && cfg.local_dns_addr.is_some())\n}","tryCatchPattern":"// expect() panics — validate before construction\nif !dns_config_ok(&config) {\n    eprintln!(\"invalid dns config: local_dns_addr is required\");\n    std::process::exit(2);\n}\nlet server = LocalServer::new(context, config)?;","preventionTips":["When switching a local config to protocol = \"dns\", add local_dns_addr and remote_dns_addr together","Start from the official dns-tunnel example config rather than editing a socks config in place","Add a startup config check that dns mode has local address, local_dns_addr, and remote_dns_addr","Treat LocalServer::new panics as config invariant violations — validate all inputs first"],"tags":["dns","configuration","missing-field","panic"],"backgroundTag":"missing-required-config-field","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"}