Kuberwastaken/claurst · error
Callback server dropped
Error message
Callback server dropped
What it means
In wait_for_auth_code_impl, the mpsc receiver for the loopback callback server yielded None, meaning the callback server task terminated without sending an authorization code. The unwrap_or_else converts that channel closure into this error. Normal result delivery would have carried either a code or the server's own error.
Solutions
- Re-run the OAuth login flow; this is usually a one-off task failure.
- Check that the loopback redirect port is free and not blocked by a firewall.
- Use the manual paste path (paste the auth code into stdin) if the callback server cannot bind.
- Check application logs for a panic in the callback server task.
Defensive patterns
Strategy: fallback
Validate before calling
// ensure the callback port is bindable before starting the server
TcpListener::bind(("127.0.0.1", port)).await
.map_err(|e| anyhow!("callback port {} unavailable: {}", port, e))?; Try / catch
// fall back to manual paste when the callback channel dies
tokio::select! {
result = cb_rx => result.unwrap_or_else(|_| Err(anyhow!("Callback server dropped"))),
_ = prompt_manual_paste() => prompt_manual_paste().await,
} Prevention
- Check the loopback port is free and not blocked by a firewall before starting login
- Keep a manual paste fallback path ready
- Monitor the callback task and log panics so drops are diagnosable
When it happens
Trigger: tokio::select! branch `result = cb_rx` receives Err (channel closed) instead of a message: the local HTTP callback server task in run_oauth_login_flow_with_label panicked, was dropped, or shut down before the browser hit the redirect.
Common situations: Port conflict killing the loopback server at startup; another agent/process killing the task; a panic inside the callback handler; OS firewall or sandbox terminating the listener.
Related errors
- Missing code or state in OAuth callback
- OAuth state mismatch — possible CSRF attack
- OAuth callback path mismatch: expected
- No query string in callback
- models endpoint returned
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/883a7b68bed63c3f.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/cli/src/oauth_flow.rs:531
let _ = cb_tx.send(result);
});
let (paste_tx, paste_rx) = tokio::sync::oneshot::channel::<String>();
tokio::spawn(async move {
if let Ok(line) = read_line_from_stdin().await {
let trimmed = line.trim().to_string();
if !trimmed.is_empty() {
let _ = paste_tx.send(trimmed);
}
}
});
tokio::select! {
result = cb_rx => {
// Loopback callback: code came clean from the query string and was
// authorized against the localhost redirect_uri.
result
.unwrap_or_else(|_| Err(anyhow::anyhow!("Callback server dropped")))
.map(|code| (code, false))
}
code = paste_rx => {
// Manual paste: the page hands back "<code>#<state>"; keep only the
// code part. This path authorized against MANUAL_REDIRECT_URL.
let raw = code.map_err(|_| anyhow::anyhow!("Stdin closed unexpectedly"))?;
let code_only = raw.split('#').next().unwrap_or(&raw).trim().to_string();
Ok((code_only, true))
}
_ = tokio::time::sleep(Duration::from_secs(120)) => {
bail!("Authentication timed out after 120 seconds")
}
}
}
View on GitHub (pinned to b0637c97ec)