{"record":{"id":"d1c499d14572a62c","repo":"shadowsocks/shadowsocks-rust","slug":"plugin-mode-must-be-one-of-tcp-only-default-d1c499","errorCode":null,"errorMessage":"plugin-mode must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`","messagePattern":"plugin-mode must be one of `tcp_only` \\(default\\), `udp_only` and `tcp_and_udp`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/service/server.rs","lineNumber":377,"sourceCode":"                Ok(sc) => sc,\n                Err(err) => {\n                    panic!(\"failed to create ServerConfig, error: {}\", err);\n                }\n            };\n            if let Some(timeout) = timeout {\n                sc.set_timeout(timeout);\n            }\n\n            if let Some(p) = matches.get_one::<String>(\"PLUGIN\").cloned() {\n                let plugin = PluginConfig {\n                    plugin: p,\n                    plugin_opts: matches.get_one::<String>(\"PLUGIN_OPT\").cloned(),\n                    plugin_args: Vec::new(),\n                    plugin_mode: matches\n                        .get_one::<String>(\"PLUGIN_MODE\")\n                        .map(|x| {\n                            x.parse::<Mode>()\n                                .expect(\"plugin-mode must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`\")\n                        })\n                        .unwrap_or(Mode::TcpOnly),\n                };\n\n                sc.set_plugin(plugin);\n            }\n\n            // For historical reason, servers that are created from command-line have to be tcp_only.\n            sc.set_mode(Mode::TcpOnly);\n\n            if matches.get_flag(\"UDP_ONLY\") {\n                sc.set_mode(Mode::UdpOnly);\n            }\n\n            if matches.get_flag(\"TCP_AND_UDP\") {\n                sc.set_mode(Mode::TcpAndUdp);\n            }\n","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/src/service/server.rs#L359-L395","documentation":"This panic comes from an `.expect()` on `str::parse::<Mode>()` while building the plugin configuration from the `--plugin-mode` CLI flag. The string is parsed into the shadowsocks `Mode` enum, which only accepts `tcp_only`, `udp_only`, and `tcp_and_udp`; any other value panics with this message instead of returning a graceful config error.","triggerScenarios":"Passing `--plugin-mode` (PLUGIN_OPT/PLUGIN_MODE matches in src/service/server.rs:377) with a value that is not exactly `tcp_only`, `udp_only`, or `tcp_and_udp`, e.g. `tcp`, `TCP_ONLY`, `udp`, or a typo like `tcp-and-udp`.","commonSituations":"Users copying plugin flags from shadowsocks-libev or other implementations that use different mode spellings (`tcp_and_udp` vs `TCP`), typos in launch scripts or systemd units, case mistakes since parsing is case-sensitive.","solutions":["Set --plugin-mode to exactly one of `tcp_only`, `udp_only`, or `tcp_and_udp` (lowercase, underscores).","Omit --plugin-mode entirely to get the default `tcp_only`.","If the value comes from a script/config file, validate it against the three allowed strings before launching.","Wrap the parse in a checked path (e.g. `Mode::from_str` with error handling) instead of `.expect` if patching the code."],"exampleFix":"// before\nsslocal --plugin obfs --plugin-opts \"obfs=http\" --plugin-mode TCP_ONLY\n// after\nsslocal --plugin obfs --plugin-opts \"obfs=http\" --plugin-mode tcp_only","handlingStrategy":"validation","validationCode":"const VALID_MODES: [&str; 3] = [\"tcp_only\", \"udp_only\", \"tcp_and_udp\"];\nif !VALID_MODES.contains(&plugin_mode.as_str()) {\n    panic!(\"plugin-mode must be one of tcp_only, udp_only, tcp_and_udp, got: {plugin_mode}\");\n}","typeGuard":"fn is_valid_mode(s: &str) -> bool {\n    matches!(s, \"tcp_only\" | \"udp_only\" | \"tcp_and_udp\")\n}","tryCatchPattern":null,"preventionTips":["Keep --plugin-mode values lowercase with underscores exactly as documented.","Store launch commands in scripts and validate flags with shellcheck or a lint pass.","Omit the flag when the default (tcp_only) is desired."],"tags":["cli","enum-parse","panic","configuration"],"backgroundTag":"invalid-enum-value","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}