Kuberwastaken/claurst · error · anyhow::Error

Failed to accept OAuth callback connection

Error message

Failed to accept OAuth callback connection: {}

What it means

Raised when listener.accept() itself returns Err (distinct from the timeout case). The TCP listener failed to accept an incoming callback connection, typically because the listener was closed or the OS rejected the accept.

Solutions

  1. Check the inner error ({} placeholder) for the errno (e.g. EMFILE) and address it
  2. Raise the fd limit (ulimit -n) if EMFILE/ENFILE
  3. Ensure no other code closes the listener while the auth session is waiting
  4. Retry the auth flow after fixing the environment

Example fix

# Raise fd limit
ulimit -n 4096
Defensive patterns

Strategy: retry

Try / catch

match wait_for_authorization_code(listener, host, path, Some(state)).await {
    Ok(code) => code,
    Err(e) if e.to_string().contains("accept OAuth callback connection") => {
        eprintln!("accept failed: {e}; retrying");
        retry_flow().await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: wait_for_authorization_code calling accept() after the listener/socket was closed or the process hit an fd limit (EMFILE/ENFILE); the loopback interface going down mid-flow.

Common situations: Too many open files exhausting fds; another thread/task dropped the TcpListener; sandbox/LSM policies interfering with socket operations.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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

Appendix: source

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

        redirect_url.path().to_string()
    };
    let listener = TcpListener::bind((host.as_str(), port))
        .await
        .map_err(|e| anyhow::anyhow!("Failed to bind OAuth callback listener on {}:{}: {}", host, port, e))?;

    Ok((listener, host, callback_path))
}

async fn wait_for_authorization_code(
    listener: TcpListener,
    host: &str,
    callback_path: &str,
    expected_state: Option<&str>,
) -> anyhow::Result<String> {
    let (mut socket, _) = tokio::time::timeout(Duration::from_secs(180), listener.accept())
        .await
        .map_err(|_| anyhow::anyhow!("Timeout waiting for OAuth callback"))?
        .map_err(|e| anyhow::anyhow!("Failed to accept OAuth callback connection: {}", e))?;

    let (reader, mut writer) = socket.split();
    let mut reader = BufReader::new(reader);
    let mut request_line = String::new();
    reader
        .read_line(&mut request_line)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to read OAuth callback request: {}", e))?;
    loop {
        let mut header = String::new();
        reader
            .read_line(&mut header)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to read OAuth callback headers: {}", e))?;
        if header.trim().is_empty() {
            break;
        }
    }

View on GitHub (pinned to b0637c97ec)