shadowsocks/shadowsocks-rust · error
`local-addr` is required for protocol
Error message
`local-addr` is required for protocol {} What it means
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.
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`
Example fix
// before sslocal --protocol dns -s example.com:8388 -p pass // after sslocal --protocol dns -b 127.0.0.1:1053 -s example.com:8388 -p pass
Defensive patterns
Strategy: validation
Validate before calling
let protocol = std::env::var("PROTOCOL").unwrap_or_else(|_| "socks".into());
if protocol != "tun" && !args.iter().any(|a| a == "-b" || a.starts_with("--local-addr")) {
panic!("--local-addr is required for protocol {protocol}");
} Try / catch
// panic is not catchable in stable Rust; check exit status when spawning:
let status = Command::new("sslocal").args(&args).status()?;
if !status.success() { /* grep stderr for '`local-addr` is required' */ } Prevention
- 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
When it happens
Trigger: 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`.
Common situations: 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.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- dns
- failed to create ServerConfig, error
- failed to create ServerConfig, error
- `method` is required
- `method` is required
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/b83bf9c6b9226210.
Report an issue: GitHub.
Appendix: source
Thrown at src/service/local.rs:738
#[cfg(feature = "local-redir")]
Some("redir") => ProtocolType::Redir,
#[cfg(feature = "local-dns")]
Some("dns") => ProtocolType::Dns,
#[cfg(feature = "local-tun")]
Some("tun") => ProtocolType::Tun,
Some(p) => panic!("not supported `protocol` \"{p}\""),
None => ProtocolType::Socks,
};
let mut local_config = LocalConfig::new(protocol);
match matches.get_one::<ServerAddr>("LOCAL_ADDR").cloned() {
Some(local_addr) => local_config.addr = Some(local_addr),
None => {
#[cfg(feature = "local-tun")]
if protocol == ProtocolType::Tun {
// `tun` protocol doesn't need --local-addr
} else {
panic!("`local-addr` is required for protocol {}", protocol.as_str());
}
}
}
if let Some(udp_bind_addr) = matches.get_one::<ServerAddr>("UDP_BIND_ADDR").cloned() {
local_config.udp_addr = Some(udp_bind_addr);
}
if let Some(udp_associate_addr) = matches.get_one::<ServerAddr>("UDP_ASSOCIATE_ADDR").cloned() {
local_config.udp_associate_addr = Some(udp_associate_addr);
}
#[cfg(feature = "local-tunnel")]
if let Some(addr) = matches.get_one::<Address>("FORWARD_ADDR").cloned() {
local_config.forward_addr = Some(addr);
}
#[cfg(feature = "local-redir")]View on GitHub (pinned to 8eb0f0a65b)