shadowsocks/shadowsocks-rust · error

malformed `plugin_mode`, must be one of `tcp_only`, `udp_onl

Error message

malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`

What it means

Thrown when parsing a server entry with a plugin: the `plugin_mode` string cannot be parsed into a Mode. Only `tcp_only`, `udp_only`, and `tcp_and_udp` are accepted; anything else yields ErrorKind::Malformed.

Source

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

                    }
                };
                nsvr.set_source(server_source);
                nsvr.set_mode(global_mode);

                if let Some(ref p) = config.plugin {
                    // SIP008 allows "plugin" to be an empty string
                    // Empty string implies "no plugin"
                    if !p.is_empty() {
                        let plugin = PluginConfig {
                            plugin: p.clone(),
                            plugin_opts: config.plugin_opts.clone(),
                            plugin_args: config.plugin_args.clone().unwrap_or_default(),
                            plugin_mode: match config.plugin_mode {
                                None => Mode::TcpOnly,
                                Some(ref mode) => match mode.parse::<Mode>() {
                                    Ok(m) => m,
                                    Err(..) => {
                                        let e = Error::new(
                                            ErrorKind::Malformed,
                                            "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`",
                                            None,
                                        );
                                        return Err(e);
                                    }
                                },
                            },
                        };
                        nsvr.set_plugin(plugin);
                    }
                }

                if let Some(timeout) = config.timeout.map(Duration::from_secs) {
                    nsvr.set_timeout(timeout);
                }

                nconfig.server.push(ServerInstanceConfig::with_server_config(nsvr));

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Set plugin_mode to exactly one of `tcp_only`, `udp_only`, or `tcp_and_udp`
  2. Remove the `plugin_mode` field if the default (TcpOnly) is acceptable
  3. Check case: values must be lowercase as listed

Example fix

// before
{"plugin": "v2ray-plugin", "plugin_mode": "tcp+udp"}
// after
{"plugin": "v2ray-plugin", "plugin_mode": "tcp_and_udp"}
Defensive patterns

Strategy: validation

Validate before calling

const MODES: &[&str] = &["tcp_only", "udp_only", "tcp_and_udp"];
// before load: if let Some(m) = obj.get("plugin_mode") { assert!(MODES.contains(&m.as_str().unwrap_or(""))); }

Try / catch

match mode_str.parse::<shadowsocks::config::Mode>() {
    Ok(m) => m,
    Err(_) => { eprintln!("plugin_mode must be tcp_only|udp_only|tcp_and_udp"); return; }
}

Prevention

When it happens

Trigger: Config parsing where `plugin_mode` is set to an unrecognized value: misspellings like `tcp`, `TCP`, `tcp+udp`, `both`, or translated labels from other tools.

Common situations: Converting configs from other shadowsocks GUIs that use different plugin-mode spellings; typos; leaving a placeholder value in the JSON.

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