{"record":{"id":"b83bf9c6b9226210","repo":"shadowsocks/shadowsocks-rust","slug":"local-addr-is-required-for-protocol","errorCode":null,"errorMessage":"`local-addr` is required for protocol {}","messagePattern":"`local-addr` is required for protocol (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/service/local.rs","lineNumber":738,"sourceCode":"                #[cfg(feature = \"local-redir\")]\n                Some(\"redir\") => ProtocolType::Redir,\n                #[cfg(feature = \"local-dns\")]\n                Some(\"dns\") => ProtocolType::Dns,\n                #[cfg(feature = \"local-tun\")]\n                Some(\"tun\") => ProtocolType::Tun,\n                Some(p) => panic!(\"not supported `protocol` \\\"{p}\\\"\"),\n                None => ProtocolType::Socks,\n            };\n\n            let mut local_config = LocalConfig::new(protocol);\n            match matches.get_one::<ServerAddr>(\"LOCAL_ADDR\").cloned() {\n                Some(local_addr) => local_config.addr = Some(local_addr),\n                None => {\n                    #[cfg(feature = \"local-tun\")]\n                    if protocol == ProtocolType::Tun {\n                        // `tun` protocol doesn't need --local-addr\n                    } else {\n                        panic!(\"`local-addr` is required for protocol {}\", protocol.as_str());\n                    }\n                }\n            }\n\n            if let Some(udp_bind_addr) = matches.get_one::<ServerAddr>(\"UDP_BIND_ADDR\").cloned() {\n                local_config.udp_addr = Some(udp_bind_addr);\n            }\n\n            if let Some(udp_associate_addr) = matches.get_one::<ServerAddr>(\"UDP_ASSOCIATE_ADDR\").cloned() {\n                local_config.udp_associate_addr = Some(udp_associate_addr);\n            }\n\n            #[cfg(feature = \"local-tunnel\")]\n            if let Some(addr) = matches.get_one::<Address>(\"FORWARD_ADDR\").cloned() {\n                local_config.forward_addr = Some(addr);\n            }\n\n            #[cfg(feature = \"local-redir\")]","sourceCodeStart":720,"sourceCodeEnd":756,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/src/service/local.rs#L720-L756","documentation":"When a `--protocol` (or `--local-addr`) is given but `--local-addr` (LOCAL_ADDR) is absent, create() requires it for every protocol except `tun`, which binds no local listening socket and is exempt. If the exemption doesn't apply, it panics. This enforces that the local server knows where to listen for client traffic.","triggerScenarios":"Running `sslocal --protocol http|socks|tunnel|redir|dns` without `--local-addr` / `-b <addr>` on a build with local-tun enabled (the cfg'd if/else panics in the else branch); equivalently on non-tun builds any protocol without `-b`.","commonSituations":"Users configuring a TUN-less DNS/HTTP proxy from a TUN tutorial that omitted `-b`; scripts migrated from config-file usage where `local_addr` was set in JSON but CLI flags were added piecemeal.","solutions":["Add `--local-addr <ip:port>` (or `-b`), e.g. `sslocal -b 127.0.0.1:1080 -s server:8388 -p pass`","If you truly want TUN mode, pass `--protocol tun` (no local-addr needed) and build with the local-tun feature","Switch to a JSON config file where `local_addr` is set, and launch sslocal with `-c config.json`"],"exampleFix":"// before\nsslocal --protocol dns -s example.com:8388 -p pass\n// after\nsslocal --protocol dns -b 127.0.0.1:1053 -s example.com:8388 -p pass","handlingStrategy":"validation","validationCode":"let protocol = std::env::var(\"PROTOCOL\").unwrap_or_else(|_| \"socks\".into());\nif protocol != \"tun\" && !args.iter().any(|a| a == \"-b\" || a.starts_with(\"--local-addr\")) {\n    panic!(\"--local-addr is required for protocol {protocol}\");\n}","typeGuard":null,"tryCatchPattern":"// panic is not catchable in stable Rust; check exit status when spawning:\nlet status = Command::new(\"sslocal\").args(&args).status()?;\nif !status.success() { /* grep stderr for '`local-addr` is required' */ }","preventionTips":["Always pass `-b/--local-addr` unless using --protocol tun","Keep a wrapper script that injects a default `-b 127.0.0.1:1080` when omitted","Prefer JSON config files where local_addr is explicit and validated up front"],"tags":["cli","configuration","missing-argument"],"backgroundTag":"missing-required-argument","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"}