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

  1. Retry the login and complete the browser consent within the timeout window
  2. Verify the redirect_uri/port used in the auth URL matches what start_callback_server listens on
  3. Ensure popups/external browser are allowed to open the authorization URL
  4. Check that the state/login_id is not being cleared by a concurrent login attempt
  5. 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

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


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/1a5d85195f250e21. Report an issue: GitHub.