{"record":{"id":"98c748f4e362ed7a","repo":"shadowsocks/shadowsocks-rust","slug":"missing-local-port","errorCode":null,"errorMessage":"missing `local_port`","messagePattern":"missing `local_port`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/shadowsocks-service/src/config.rs","lineNumber":1802,"sourceCode":"        if let Some(m) = config.mode {\n            match m.parse::<Mode>() {\n                Ok(xm) => global_mode = xm,\n                Err(..) => {\n                    let e = Error::new(\n                        ErrorKind::Malformed,\n                        \"malformed `mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`\",\n                        None,\n                    );\n                    return Err(e);\n                }\n            }\n        }\n\n        match config_type {\n            ConfigType::Local => {\n                // Standard config\n                if config.local_address.is_some() && config.local_port.unwrap_or(0) == 0 {\n                    let err = Error::new(ErrorKind::MissingField, \"missing `local_port`\", None);\n                    return Err(err);\n                }\n\n                if let Some(local_port) = config.local_port {\n                    // local_port won't be 0, it was checked above\n                    assert_ne!(local_port, 0);\n\n                    let local_addr =\n                        get_local_address(config.local_address, local_port, config.ipv6_first.unwrap_or(false));\n\n                    // shadowsocks uses SOCKS5 by default\n                    let mut local_config = LocalConfig::new(ProtocolType::Socks);\n                    local_config.addr = Some(local_addr);\n                    local_config.mode = global_mode;\n                    local_config.protocol = match config.protocol {\n                        None => ProtocolType::Socks,\n                        Some(p) => match p.parse::<ProtocolType>() {\n                            Ok(p) => p,","sourceCodeStart":1784,"sourceCodeEnd":1820,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/config.rs#L1784-L1820","documentation":"In the final Local-type validation (config.rs), if `local_address` is set but `local_port` is missing or 0, the library returns ErrorKind::MissingField \"missing `local_port`\". A local server listens on address:port, so a port must accompany the address. The check also asserts port != 0 afterwards.","triggerScenarios":"Calling Config::validate() (or Config::load with ConfigType::Local) where config.local_address is Some but config.local_port is None or Some(0).","commonSituations":"A JSON config specifying \"local_address\" but omitting \"local_port\"; setting local_port to 0 expecting an OS-assigned port (not allowed here); programmatically built configs missing the local_port setter.","solutions":["Add a non-zero `local_port` to the configuration (e.g. \"local_port\": 1080).","In code, set config.local_port = Some(port) before validating.","If only the address should be configured, also verify the port key is not being overwritten to 0 by template/ENV logic."],"exampleFix":"// before\n{ \"local_address\": \"127.0.0.1\" }\n// after\n{ \"local_address\": \"127.0.0.1\", \"local_port\": 1080 }","handlingStrategy":"validation","validationCode":"if raw.get(\"local_address\").is_some() && raw.get(\"local_port\").and_then(|p| p.as_u64()).unwrap_or(0) == 0 {\n    return Err(\"local_address requires a non-zero local_port\");\n}","typeGuard":"fn local_port_ok(cfg: &Config) -> bool {\n    cfg.local_address.is_none() || matches!(cfg.local_port, Some(p) if p != 0)\n}","tryCatchPattern":"match Config::load(path) {\n    Ok(cfg) => start(cfg),\n    Err(e) if e.to_string().contains(\"missing `local_port`\") => eprintln!(\"set a non-zero local_port when local_address is specified\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Always set local_port together with local_address in configs.","Do not use port 0 expecting dynamic assignment; it is rejected.","Validate generated configs before deployment."],"tags":["config","port","missing-field"],"backgroundTag":"missing-required-config-field","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"}