shadowsocks/shadowsocks-rust · error
`local_port` cannot be 0
Error message
`local_port` cannot be 0
What it means
Raised when a local server config entry specifies `local_port` with the value 0. Port 0 is not a valid fixed listen port for the local forwarder (it would normally mean 'OS-assigned', which the config loader explicitly rejects), so it is treated as a malformed config.
Source
Thrown at crates/shadowsocks-service/src/config.rs:1876
None => ProtocolType::Socks,
Some(p) => match p.parse::<ProtocolType>() {
Ok(p) => p,
Err(..) => {
let err = Error::new(
ErrorKind::Malformed,
"`protocol` invalid",
Some(format!("unrecognized protocol {p}")),
);
return Err(err);
}
},
};
let mut local_config = LocalConfig::new(protocol);
if let Some(local_port) = local.local_port {
if local_port == 0 {
let err = Error::new(ErrorKind::Malformed, "`local_port` cannot be 0", None);
return Err(err);
}
let local_addr =
get_local_address(local.local_address, local_port, config.ipv6_first.unwrap_or(false));
local_config.addr = Some(local_addr);
} else if local.local_address.is_some() {
let err = Error::new(ErrorKind::Malformed, "missing `local_port`", None);
return Err(err);
}
if let Some(local_udp_port) = local.local_udp_port {
if local_udp_port == 0 {
let err = Error::new(ErrorKind::Malformed, "`local_udp_port` cannot be 0", None);
return Err(err);
}
let local_udp_addr = get_local_address(View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Set `local_port` to a concrete port in the valid range (1-65535), e.g. 1080 for SOCKS.
- Remove the `local_port` key if the server should not bind a TCP local port (note: `local_address` without `local_port` triggers a different error).
- Fix the upstream code/script that generated the placeholder 0.
Example fix
// before
{ "protocol": "socks", "local_port": 0 }
// after
{ "protocol": "socks", "local_port": 1080 } Defensive patterns
Strategy: validation
Validate before calling
fn validate_local_port(cfg: &serde_json::Value) -> Result<(), String> {
if let Some(p) = cfg.get("local_port") {
let port = p.as_u64().ok_or("local_port must be an integer")?;
if port == 0 || port > 65535 {
return Err(format!("local_port {port} out of range 1-65535"));
}
}
Ok(())
} Try / catch
match LocalConfig::load_from(config_path) {
Ok(cfg) => start(cfg),
Err(e) if e.to_string().contains("local_port") => {
eprintln!("Fix local_port in config: {e}");
std::process::exit(1);
}
Err(e) => return Err(e.into()),
} Prevention
- Never use 0 as a placeholder port; omit the field instead.
- Range-check all ports (1-65535) in a config preflight validator.
- When generating configs, treat port=0 from the source as an error, not a default.
- Check for privileged-port needs only when you pick <1024, not 0.
When it happens
Trigger: A config entry (global `local_port` or a per-`local` entry) contains `"local_port": 0`, e.g. as a placeholder that was never filled in.
Common situations: Template configs left with 0 as placeholder; programmatically generated configs where a port lookup failed and defaulted to 0; user misunderstanding that 0 means 'auto-assign'.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- `local_udp_port` cannot be 0
- `server_port` shouldn't be 0
- `server` shouldn't be an empty string, `server_port` shouldn
- missing `local_port`
- `protocol` invalid
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/90d398cffa5c8961.
Report an issue: GitHub.