shadowsocks/shadowsocks-rust · error

invalid `mode`

Error message

invalid `mode`

What it means

Raised when a local config entry's `mode` string cannot be parsed into the `Mode` type. Mode controls which relays are enabled (e.g. "tcp_only", "udp_only", "tcp_and_udp"); an unrecognized value is rejected as Malformed instead of silently defaulting.

Source

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

                                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;
                        }

                        match local.mode {
                            Some(mode) => match mode.parse::<Mode>() {
                                Ok(mode) => local_config.mode = mode,
                                Err(..) => {
                                    let err = Error::new(ErrorKind::Malformed, "invalid `mode`", None);
                                    return Err(err);
                                }
                            },
                            None => {
                                // DNS server runs in `TcpAndUdp` mode by default to maintain backwards compatibility
                                // see https://github.com/shadowsocks/shadowsocks-rust/issues/1281
                                let mode = match protocol {
                                    #[cfg(feature = "local-dns")]
                                    ProtocolType::Dns => Mode::TcpAndUdp,
                                    _ => global_mode,
                                };

                                local_config.mode = mode;
                            }
                        }

                        #[cfg(feature = "local-tunnel")]
                        if let Some(forward_address) = local.forward_address {

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Use an exact accepted Mode value: "tcp_only", "udp_only", or "tcp_and_udp" (verify against the Mode enum in your version).
  2. Remove the `mode` field to inherit the default (TCP-only normally; TCP-and-UDP for local-dns).
  3. Normalize case — values are matched exactly, e.g. "TCP_ONLY" may not parse.

Example fix

// before
{ "mode": "tcp-only" }
// after
{ "mode": "tcp_only" }
Defensive patterns

Strategy: validation

Validate before calling

const MODES: [&str; 3] = ["tcp_only", "udp_only", "tcp_and_udp"];
fn validate_mode(entry: &serde_json::Value) -> Result<(), String> {
    if let Some(m) = entry.get("mode") {
        let s = m.as_str().ok_or("mode must be a string")?;
        if !MODES.contains(&s) {
            return Err(format!("invalid mode: {s}"));
        }
    }
    Ok(())
}

Type guard

fn is_valid_mode(s: &str) -> bool {
    matches!(s, "tcp_only" | "udp_only" | "tcp_and_udp")
}

Try / catch

match LocalConfig::load_from(config_path) {
    Ok(cfg) => start(cfg),
    Err(e) if e.to_string().contains("invalid `mode`") => {
        eprintln!("Use tcp_only|udp_only|tcp_and_udp: {e}");
        std::process::exit(1);
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: A `local` entry contains `mode` set to a string not accepted by Mode::from_str, e.g. `"both"`, `"TCP"`, `"tcp-only"` (hyphen instead of underscore), or a typo.

Common situations: Configs copied from other tools with different mode vocabularies; case-sensitivity mistakes; older configs using removed mode names after an upgrade.

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