{"record":{"id":"a3452caf16fa4908","repo":"Kuberwastaken/claurst","slug":"failed-to-allocate-oauth-redirect-port","errorCode":null,"errorMessage":"Failed to allocate OAuth redirect port: {}","messagePattern":"Failed to allocate OAuth redirect port: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-rust/crates/mcp/src/oauth.rs","lineNumber":196,"sourceCode":"                    .to_string(),\n                token_endpoint: meta\n                    .get(\"token_endpoint\")\n                    .and_then(|value| value.as_str())\n                    .unwrap_or(fallback.token_endpoint.as_str())\n                    .to_string(),\n            })\n        }\n        Ok(_) | Err(_) => Ok(fallback),\n    }\n}\n\npub async fn begin_mcp_auth(\n    server_name: &str,\n    server_url: &str,\n) -> anyhow::Result<McpAuthSession> {\n    let metadata = fetch_oauth_metadata(server_url).await?;\n    let redirect_port = oauth_port_alloc()\n        .map_err(|e| anyhow::anyhow!(\"Failed to allocate OAuth redirect port: {}\", e))?;\n    let redirect_uri = format!(\"http://127.0.0.1:{}/callback\", redirect_port);\n    let verifier = pkce_verifier().map_err(|e| anyhow::anyhow!(\"Failed to generate PKCE verifier: {}\", e))?;\n    let auth_url = build_mcp_auth_url(\n        &metadata.authorization_endpoint,\n        &redirect_uri,\n        &verifier,\n    );\n\n    Ok(McpAuthSession {\n        server_name: server_name.to_string(),\n        auth_url,\n        redirect_uri,\n        verifier,\n        metadata,\n    })\n}\n\nasync fn bind_callback_listener(","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/mcp/src/oauth.rs#L178-L214","documentation":"begin_mcp_auth() binds a local loopback port to receive the OAuth redirect callback. If the OS refuses to allocate a port (listener bind failure), this error is thrown before the authorization URL is built. Without a local callback port the browser flow cannot complete.","triggerScenarios":"oauth_port_alloc() fails inside begin_mcp_auth — no free ports in the allowed range, port blocked by policy, or socket bind errors from resource limits.","commonSituations":"Firewall/EDR blocking loopback listeners; all ports in the OAuth callback range occupied by stale processes; running inside a container without loopback networking; ulimit exhausting file descriptors.","solutions":["Check for stale processes holding the callback port range and kill them (lsof -i)","Verify loopback listeners are permitted (container security policy, firewall rules)","Free file descriptors / raise ulimit if resource limits are hit","Retry — the allocator picks a port each attempt, so a transient bind failure may pass"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// probe that a loopback listener is allowed before starting the flow\nlet probe = std::net::TcpListener::bind(\"127.0.0.1:0\")\n    .context(\"loopback listeners are not permitted in this environment\")?;","typeGuard":null,"tryCatchPattern":"let port = oauth_port_alloc().map_err(|e| {\n    eprintln!(\"cannot bind OAuth callback port (firewall/stale listener?): {e}\");\n    e\n})?;","preventionTips":["Kill stale dev servers holding the callback port range","Allow loopback listeners in container/firewall policies for auth flows","Check ulimit -n if binds fail under many open sockets","Retry the flow — port allocation is per-attempt and transient failures resolve"],"tags":["oauth","network","port-allocation"],"backgroundTag":"address-already-in-use","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}