shadowsocks/shadowsocks-rust · error

not supported `protocol` "{p}"

Error message

not supported `protocol` "{p}"

What it means

The shadowsocks local server's CLI `create` fn maps the `--protocol` flag value to a ProtocolType enum. If the value is not one of the compiled-in variants (socks, http, tunnel, redir, dns, tun — some behind cargo features), it panics with this message. Note that protocols gated behind disabled features also land here, so a valid name can still panic if the feature isn't compiled in.

Source

Thrown at src/service/local.rs:726

            // A socket `protect_path` in CWD
            // Same as shadowsocks-libev's android.c
            config.outbound_vpn_protect_path = Some(From::from("protect_path"));
        }

        if matches.get_raw("LOCAL_ADDR").is_some() || matches.get_raw("PROTOCOL").is_some() {
            let protocol = match matches.get_one::<String>("PROTOCOL").map(|s| s.as_str()) {
                Some("socks") => ProtocolType::Socks,
                #[cfg(feature = "local-http")]
                Some("http") => ProtocolType::Http,
                #[cfg(feature = "local-tunnel")]
                Some("tunnel") => ProtocolType::Tunnel,
                #[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);

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Fix the `--protocol` value to one of: socks, http, tunnel, redir, dns, tun
  2. Rebuild sslocal with the matching feature enabled, e.g. `cargo build --features local-tun` for `--protocol tun`
  3. Check `sslocal --help` / build features to see which protocols the installed binary supports
  4. Drop the `--protocol` flag entirely to get the default SOCKS5 local server

Example fix

// before
sslocal --protocol tun -b 127.0.0.1:1080 -s example.com:8388 -p pass
// after (build with feature first)
cargo build --features local-tun
sslocal --protocol tun -s example.com:8388 -p pass
Defensive patterns

Strategy: validation

Validate before calling

let supported = ["socks", "http", "tunnel", "redir", "dns", "tun"];
let p = std::env::args().nth(/* protocol position */ 0).unwrap_or_default();
if !supported.contains(&p.as_str()) {
    eprintln!("unsupported protocol {p}; supported: {supported:?}");
    std::process::exit(2);
}

Try / catch

// panic is not catchable in stable Rust; wrap process spawn instead:
let status = Command::new("sslocal").args(&args).status()?;
if !status.success() { /* inspect stderr for 'not supported `protocol`' */ }

Prevention

When it happens

Trigger: Running `sslocal --protocol <p> ...` with a misspelled protocol name (e.g. `sock`, `tunn`), or with a valid name (http/tunnel/redir/dns/tun) whose cargo feature (local-http, local-tunnel, local-redir, local-dns, local-tun) was not enabled at build time, so the match arm doesn't exist.

Common situations: Typo in a shell alias or systemd unit; using a binary from a package manager built with default features while the docs show feature-gated protocols; copying examples that use `tun` into an environment with a minimal build.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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