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
- Check the inner error ({} placeholder) for the errno (e.g. EMFILE) and address it
- Raise the fd limit (ulimit -n) if EMFILE/ENFILE
- Ensure no other code closes the listener while the auth session is waiting
- 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
- Keep fd limits healthy (ulimit -n)
- Never drop the TcpListener while an auth session is pending
- Avoid sandboxes that restrict socket ops mid-run
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
- API key creation failed
- Bridge register: server returned
- exchange_code: HTTP
- Failed to accept connection
- Failed to allocate OAuth redirect port
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)