Kuberwastaken/claurst · error · anyhow::Error

Failed to allocate OAuth redirect port

Error message

Failed to allocate OAuth redirect port: {}

What it means

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.

Solutions

  1. Check for stale processes holding the callback port range and kill them (lsof -i)
  2. Verify loopback listeners are permitted (container security policy, firewall rules)
  3. Free file descriptors / raise ulimit if resource limits are hit
  4. Retry — the allocator picks a port each attempt, so a transient bind failure may pass
Defensive patterns

Strategy: try-catch

Validate before calling

// probe that a loopback listener is allowed before starting the flow
let probe = std::net::TcpListener::bind("127.0.0.1:0")
    .context("loopback listeners are not permitted in this environment")?;

Try / catch

let port = oauth_port_alloc().map_err(|e| {
    eprintln!("cannot bind OAuth callback port (firewall/stale listener?): {e}");
    e
})?;

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/a3452caf16fa4908. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/mcp/src/oauth.rs:196

                    .to_string(),
                token_endpoint: meta
                    .get("token_endpoint")
                    .and_then(|value| value.as_str())
                    .unwrap_or(fallback.token_endpoint.as_str())
                    .to_string(),
            })
        }
        Ok(_) | Err(_) => Ok(fallback),
    }
}

pub async fn begin_mcp_auth(
    server_name: &str,
    server_url: &str,
) -> anyhow::Result<McpAuthSession> {
    let metadata = fetch_oauth_metadata(server_url).await?;
    let redirect_port = oauth_port_alloc()
        .map_err(|e| anyhow::anyhow!("Failed to allocate OAuth redirect port: {}", e))?;
    let redirect_uri = format!("http://127.0.0.1:{}/callback", redirect_port);
    let verifier = pkce_verifier().map_err(|e| anyhow::anyhow!("Failed to generate PKCE verifier: {}", e))?;
    let auth_url = build_mcp_auth_url(
        &metadata.authorization_endpoint,
        &redirect_uri,
        &verifier,
    );

    Ok(McpAuthSession {
        server_name: server_name.to_string(),
        auth_url,
        redirect_uri,
        verifier,
        metadata,
    })
}

async fn bind_callback_listener(

View on GitHub (pinned to b0637c97ec)