{"record":{"id":"72ece2bf9d133811","repo":"Hmbown/CodeWhale","slug":"invalid-mcp-oauth-callback-port-0","errorCode":null,"errorMessage":"invalid MCP OAuth callback port 0","messagePattern":"invalid MCP OAuth callback port 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp/oauth.rs","lineNumber":1588,"sourceCode":"    server_name: String,\n    server_url: String,\n}\n\nimpl OauthLoginFlow {\n    #[allow(clippy::too_many_arguments)]\n    async fn new(\n        server_name: &str,\n        server_url: &str,\n        client: McpHttpClient,\n        scopes: &[String],\n        oauth_client_id: Option<&str>,\n        oauth_resource: Option<&str>,\n        callback_port: Option<u16>,\n        callback_url: Option<&str>,\n    ) -> Result<Self> {\n        let bind_host = callback_bind_host(callback_url);\n        let bind_addr = match callback_port {\n            Some(0) => bail!(\"invalid MCP OAuth callback port 0\"),\n            Some(port) => format!(\"{bind_host}:{port}\"),\n            None => format!(\"{bind_host}:0\"),\n        };\n        let listener = TcpListener::bind(&bind_addr)\n            .await\n            .map_err(|err| anyhow!(err))?;\n        let redirect_uri = resolve_redirect_uri(&listener, callback_url)?;\n        let callback_id = callback_id_from_server_url(server_url)?;\n        let redirect_uri = append_callback_id_to_redirect_uri(&redirect_uri, &callback_id)?;\n        let callback_path = callback_path_from_redirect_uri(&redirect_uri)?;\n\n        let (tx, rx) = oneshot::channel();\n        let guard = CallbackServerGuard {\n            accept_task: spawn_callback_server(listener, tx, callback_path),\n        };\n\n        let scope_refs: Vec<&str> = scopes.iter().map(String::as_str).collect();\n        let oauth_state = start_authorization(","sourceCodeStart":1570,"sourceCodeEnd":1606,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp/oauth.rs#L1570-L1606","documentation":"When constructing the OAuth callback listener, an explicit `callback_port` of `0` is rejected. Port `None` means 'pick an ephemeral port', but an explicit `Some(0)` is treated as a configuration mistake rather than being silently mapped to ephemeral.","triggerScenarios":"Passing `callback_port: Some(0)` into the OAuth flow constructor (e.g. from a config value of 0 for the MCP OAuth callback port).","commonSituations":"A config file with `callback_port = 0` intending 'auto-pick'; a port computed by a script that defaulted to 0 on lookup failure.","solutions":["Set the callback port to a concrete value (e.g. 8080–9999) or omit the field entirely to request an ephemeral port","Fix whatever produced `Some(0)` — replace explicit 0 with `None` in the calling code","Validate the configured port is in 1..=65535 at config-load time"],"exampleFix":"// before\ncallback_port: Some(0)\n// after\ncallback_port: None // ephemeral port, or Some(8642) for a fixed port","handlingStrategy":"validation","validationCode":"if let Some(0) = callback_port {\n    return Err(anyhow!(\"callback_port must be 1-65535 or unset\"));\n}","typeGuard":"fn valid_callback_port(p: Option<u16>) -> Option<u16> {\n    p.filter(|&p| p != 0)\n}","tryCatchPattern":null,"preventionTips":["Omit callback_port entirely for ephemeral port selection","Validate configured ports are 1..=65535 when loading config","Never translate 'auto' to Some(0); use None"],"tags":["mcp","oauth","port","config"],"backgroundTag":"invalid-config-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}