{"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":785,"sourceCode":"    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        http_headers: HashMap<String, String>,\n        env_headers: HashMap<String, String>,\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 headers = build_default_headers(&http_headers, &env_headers)?;\n        let client = apply_default_headers(crate::tls::reqwest_client_builder(), &headers)","sourceCodeStart":767,"sourceCodeEnd":803,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/mcp/oauth.rs#L767-L803","documentation":"When constructing the OAuth callback listener (oauth.rs:785), an explicit callback_port of Some(0) is rejected. Port 0 normally means 'ask the OS for an ephemeral port' in socket APIs, but here that behavior is expressed by passing None (the code binds {bind_host}:0 for that); an explicit Some(0) is therefore treated as a config mistake rather than honored.","triggerScenarios":"Invoking OAuth login with --callback-port 0, or a config/UI path that supplies callback_port: Some(0) to the callback server constructor.","commonSituations":"Users porting socket-code intuition ('pass 0 for a random port') to the OAuth callback config; automation scripts that default numeric options to 0; config generated by a tool that uses 0 as 'unset' sentinel.","solutions":["Omit the callback port entirely (None) — the client binds an ephemeral port and derives the redirect URI from it","Or specify a concrete free port in 1024-65535 that matches the redirect URI registered with the OAuth provider","Fix generators/scripts so 'automatic' is expressed by absence, not by 0"],"exampleFix":"# before\n/mcp login my-server --callback-port 0\n\n# after\n/mcp login my-server","handlingStrategy":"validation","validationCode":"if let Some(port) = callback_port {\n    ensure!(port != 0, \"callback_port 0 is invalid; omit it for an ephemeral port\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Represent 'automatic port' by omitting the option, not by 0","Validate numeric UI/script options against 0 before passing them as ports","Register the exact callback port (or a loopback redirect URI) with the OAuth provider beforehand"],"tags":["oauth","mcp","port","configuration","callback"],"backgroundTag":"invalid-port-value","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}