jlcodes99/cockpit-tools · error
Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s
Error message
Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s What it means
start_callback_server waits a bounded time for the browser to complete the Codex OAuth redirect. If the expected callback (with matching state/login_id) does not arrive before `timeout` elapses, it logs this message, sets clear_state_on_exit=true, and aborts the login session. It is the deliberate timeout path of the local OAuth flow, not an unexpected crash.
Source
Thrown at src-tauri/src/modules/codex_oauth.rs:858
loop {
let should_stop = {
let oauth_state = OAUTH_STATE.lock().unwrap();
match oauth_state.as_ref() {
Some(state) => state.state != expected_state || state.login_id != expected_login_id,
None => true,
}
};
if should_stop {
logger::log_info(&format!(
"Codex OAuth 已取消或状态已变更,停止回调监听: login_id={}",
expected_login_id
));
break;
}
if start.elapsed() > timeout {
logger::log_error(&format!(
"Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s",
expected_login_id,
callback_url,
start.elapsed().as_secs()
));
clear_state_on_exit = true;
break;
}
if let Ok(Some(request)) = server.try_recv() {
let url = request.url().to_string();
if url.starts_with("/auth/callback") {
let has_query = url.contains('?');
logger::log_info(&format!(
"Codex OAuth 收到回调请求: login_id={}, path=/auth/callback, has_query={}",
expected_login_id, has_query
));View on GitHub (pinned to 1ed8b77992)
Solutions
- Retry the login and complete the browser consent within the timeout window
- Verify the redirect_uri/port used in the auth URL matches what start_callback_server listens on
- Ensure popups/external browser are allowed to open the authorization URL
- Check that the state/login_id is not being cleared by a concurrent login attempt
- Increase the timeout if slow networks or multi-account switching are common
Example fix
// before
if start.elapsed() > timeout {
logger::log_error(&format!("Codex OAuth 回调超时: ..."));
clear_state_on_exit = true;
}
// after
if start.elapsed() > timeout {
logger::log_error(&format!("Codex OAuth 回调超时: ..."));
clear_state_on_exit = true;
// surface to caller so the UI can prompt a retry
return Err(format!("Codex OAuth 登录超时 ({}s),请重试", timeout.as_secs()));
} Defensive patterns
Strategy: retry
Validate before calling
// Before starting OAuth, verify a browser can open the auth URL and redirect_uri matches
assert_eq!(redirect_uri, format!("http://127.0.0.1:{}", port));
// and check no other login session holds the same state
if oauth_state_exists() { clear_oauth_state_if_matches(&state, &login_id); } Try / catch
match start_oauth_login(app_handle).await {
Err(e) if e.contains("超时") => {
// prompt user: 'Login timed out — please retry and complete consent in the browser'
retry_login_with_fresh_state()
}
Ok(r) => handle_response(r),
Err(e) => eprintln!("{}", e),
} Prevention
- Show a visible countdown/deadline in the UI so users complete consent in time
- Always restart the full flow (new state/verifier) after a timeout — never reuse state
- Make sure the browser/auth page actually opened (handle popup blockers)
- Keep the machine awake during login; increase timeout for slow networks
When it happens
Trigger: start_oauth_login (or ensure_callback_listener_for_state) started the listener, but the user never completed the browser consent, the redirect URL/port mismatched, or the callback POST/GET was dropped — so elapsed() > timeout fires.
Common situations: User leaves the consent tab open/pending or closes the browser; popup blocked so the auth page never opens; redirect_uri registered in the Codex OAuth app points to a different port so the local server never matches the state; system clock/sleep (laptop suspended) consuming the window; very short timeout configured.
Related errors
- Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s
- Claude login start 响应缺少关键字段
- 网关未在超时时间内返回唤醒结果,最后状态={}
- [AccountGroups] Failed to load groups: ${String(error)}
- Claude OAuth start 响应缺少关键字段
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/1a5d85195f250e21.
Report an issue: GitHub.