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.
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)
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
- `password` is required for server {svr_addr}
- failed to create ServerConfig, error: {}
- not supported `protocol` "{p}"
- `password` is required for server {svr_addr}
- failed to create ServerConfig, error: {}
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/b83bf9c6b9226210.
Report an issue: GitHub.