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

  1. Set `local_port` to a concrete port in the valid range (1-65535), e.g. 1080 for SOCKS.
  2. 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).
  3. 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

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


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