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

  1. Set `local_udp_port` to a concrete port (1-65535), e.g. 1080.
  2. Omit `local_udp_port` entirely if UDP relay is not needed.
  3. 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

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


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/e7b360a974f136bd. Report an issue: GitHub.