shadowsocks/shadowsocks-rust · error
`local_udp_port` cannot be 0
Error message
`local_udp_port` cannot be 0
What it means
This is a sentinel validation error raised during config deserialization of a local server entry: a local forwarder was declared with local_port = 0. Port 0 normally means 'let the OS assign an ephemeral port', which is meaningless for a declared listener whose port must be known and stable, so the parser rejects the whole config early rather than binding to an unpredictable port later. The input at fault is the local.local_port field of a LocalConfig in the user's configuration file being 0.
Source
Thrown at crates/shadowsocks-service/src/config.rs:1890
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(
local.local_udp_address,
local_udp_port,
config.ipv6_first.unwrap_or(false),
);
local_config.udp_addr = Some(local_udp_addr);
}
#[cfg(target_os = "macos")]
{
local_config.launchd_tcp_socket_name = local.launchd_tcp_socket_name;
local_config.launchd_udp_socket_name = local.launchd_udp_socket_name;
}
View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Set `local_udp_port` to a concrete port (1-65535), e.g. 1080.
- Omit `local_udp_port` entirely if UDP relay is not needed.
- Fix the generator/script that emitted 0.
Example fix
// before
{ "protocol": "socks", "local_udp_port": 0 }
// after
{ "protocol": "socks", "local_udp_port": 1080 } Defensive patterns
Strategy: validation
Validate before calling
fn validate_udp_port(entry: &serde_json::Value) -> Result<(), String> {
if let Some(p) = entry.get("local_udp_port") {
let port = p.as_u64().ok_or("local_udp_port must be an integer")?;
if port == 0 || port > 65535 {
return Err(format!("local_udp_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_udp_port") => {
eprintln!("Fix local_udp_port: {e}");
std::process::exit(1);
}
Err(e) => return Err(e.into()),
} Prevention
- Omit `local_udp_port` rather than setting 0 to disable UDP.
- Apply the same 1-65535 range check used for TCP ports.
- Fail generation-time when the source UDP port resolves to 0.
When it happens
Trigger: A `local` entry (local-http/local-tunnel contexts with UDP support) contains `"local_udp_port": 0`.
Common situations: Placeholder value left from a template; a script computing the UDP port failed and produced 0; user assumed 0 means 'no UDP' instead of omitting the field.
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_port` cannot be 0
- `udp_redir` invalid
- `server_port` shouldn't be 0
- `server` shouldn't be an empty string, `server_port` shouldn
- missing `local_port`
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/e7b360a974f136bd.
Report an issue: GitHub.