shadowsocks/shadowsocks-rust · error

`protocol` invalid

Error message

`protocol` invalid

What it means

This error is raised while parsing a shadowsocks local server configuration when the `protocol` field is present but its string value cannot be parsed into a `ProtocolType` (e.g. it is not one of "socks", "http", "tunnel", etc.). The library fails fast with ErrorKind::Malformed because an unrecognized protocol would otherwise produce a local server that cannot be started. It includes the offending value as detail (`unrecognized protocol {p}`).

Source

Thrown at crates/shadowsocks-service/src/config.rs:1822

                }

                if let Some(local_port) = config.local_port {
                    // local_port won't be 0, it was checked above
                    assert_ne!(local_port, 0);

                    let local_addr =
                        get_local_address(config.local_address, local_port, config.ipv6_first.unwrap_or(false));

                    // shadowsocks uses SOCKS5 by default
                    let mut local_config = LocalConfig::new(ProtocolType::Socks);
                    local_config.addr = Some(local_addr);
                    local_config.mode = global_mode;
                    local_config.protocol = match config.protocol {
                        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);
                            }
                        },
                    };
                    #[cfg(target_os = "macos")]
                    {
                        local_config
                            .launchd_tcp_socket_name
                            .clone_from(&config.launchd_tcp_socket_name);
                        local_config
                            .launchd_udp_socket_name
                            .clone_from(&config.launchd_udp_socket_name);
                    }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Check the config value of `protocol` and use an exact accepted variant, e.g. "socks", "http", "tunnel" (values accepted by ProtocolType::from_str).
  2. Remove the `protocol` field entirely to get the default (ProtocolType::Socks).
  3. Verify no trailing whitespace or BOM in the JSON string value.
  4. Consult the ProtocolType enum docs in the installed shadowsocks-service version, since accepted values can vary by version.

Example fix

// before
{ "protocol": "socks5", "local_port": 1080 }
// after
{ "protocol": "socks", "local_port": 1080 }
Defensive patterns

Strategy: validation

Validate before calling

const PROTOCOLS: [&str; 4] = ["socks", "http", "tunnel", "redir"]; // check your version's ProtocolType
fn validate_protocol(cfg: &serde_json::Value) -> Result<(), String> {
    match cfg.get("protocol") {
        None => Ok(()),
        Some(p) => {
            let s = p.as_str().ok_or("protocol must be a string")?;
            if PROTOCOLS.contains(&s) { Ok(()) } else { Err(format!("unrecognized protocol {s}")) }
        }
    }
}

Type guard

fn is_valid_protocol(s: &str) -> bool {
    matches!(s, "socks" | "http" | "tunnel" | "redir")
}

Try / catch

match LocalConfig::load_from(config_path) {
    Ok(cfg) => start(cfg),
    Err(e) if e.kind() == ErrorKind::Malformed => {
        eprintln!("Bad config: {e}"); // inspect `protocol` value and fix spelling
        std::process::exit(1);
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Loading a local config (JSON/URL) whose per-server or global entry has `protocol` set to a string that does not match any ProtocolType variant — e.g. `"protocol": "socks5"` or `"SOCKS"` or a typo like `"sock"`.

Common situations: Hand-edited config.json files with typos or wrong casing; configs copied from other shadowsocks implementations that use different protocol names; schema drift after upgrading where an old/alias protocol name is no longer accepted.

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/6027e87ef99d0be2. Report an issue: GitHub.