jlcodes99/cockpit-tools · error
Codex OAuth completed 命令失败: login_id={}, duration_ms={}, err
Error message
Codex OAuth completed 命令失败: login_id={}, duration_ms={}, error={} What it means
This error is logged when the frontend-invoked codex_oauth_completed command fails to finalize a Codex OAuth login: complete_oauth_login(&login_id) returned Err after the browser flow finished. The pending login state (matched by login_id and started_at_ms) could not be exchanged/validated into tokens, and the error is propagated back to the caller.
Source
Thrown at src-tauri/src/commands/codex_account_commands.rs:1949
) -> Result<(), String> {
codex_oauth::open_incognito_oauth_window(&app_handle, &auth_url)
}
/// OAuth:浏览器授权完成后按 loginId 完成登录
#[tauri::command]
pub async fn codex_oauth_login_completed(
login_id: String,
reauth_account_id: Option<String>,
) -> Result<CodexAccount, String> {
let started_at_ms = chrono::Utc::now().timestamp_millis();
logger::log_info(&format!(
"Codex OAuth completed 命令开始: login_id={}, started_at_ms={}",
login_id, started_at_ms
));
let tokens = match codex_oauth::complete_oauth_login(&login_id).await {
Ok(tokens) => tokens,
Err(e) => {
logger::log_error(&format!(
"Codex OAuth completed 命令失败: login_id={}, duration_ms={}, error={}",
login_id,
chrono::Utc::now().timestamp_millis() - started_at_ms,
e
));
return Err(e);
}
};
let account = save_codex_oauth_tokens(tokens, reauth_account_id.as_deref()).await?;
logger::log_info(&format!(
"Codex OAuth completed 命令成功: login_id={}, duration_ms={}, account_id={}, account_email={}",
login_id,
chrono::Utc::now().timestamp_millis() - started_at_ms,
account.id,
account.email
));
Ok(account)
}View on GitHub (pinned to 1ed8b77992)
Solutions
- Restart the OAuth flow from the beginning (start a fresh login to get a new login_id) rather than retrying the completed call
- Check the elapsed duration_ms in the log — a large value means the pending login likely expired; complete the flow faster
- Ensure the app isn't restarted between the OAuth start and completion steps
- Inspect the wrapped error detail to see if it's a state mismatch (double-click/duplicate flow) vs upstream token-exchange failure
Example fix
// before
let tokens = match codex_oauth::complete_oauth_login(&login_id).await {
Ok(tokens) => tokens,
Err(e) => {
logger::log_error(&format!("Codex OAuth completed 命令失败: login_id={}, duration_ms={}, error={}", login_id, chrono::Utc::now().timestamp_millis() - started_at_ms, e));
return Err(e);
}
};
// after
let tokens = match codex_oauth::complete_oauth_login(&login_id).await {
Ok(tokens) => tokens,
Err(e) => {
logger::log_error(&format!("Codex OAuth completed 命令失败: login_id={}, duration_ms={}, error={}", login_id, chrono::Utc::now().timestamp_millis() - started_at_ms, e));
// clear the dead pending state so the UI can start a clean flow immediately
let _ = codex_oauth::clear_pending_login(&login_id).await;
return Err(format!("OAuth 完成失败,请重新发起登录: {}", e));
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
// before calling completed, confirm the pending login still exists and is fresh
if !codex_oauth::has_pending_login(&login_id) {
return Err("登录会话不存在或已失效,请重新发起登录".to_string());
}
if started_at_ms.elapsed_ms() > PENDING_LOGIN_TTL_MS {
return Err("登录会话已超时,请重新发起登录".to_string());
} Try / catch
match codex_oauth::complete_oauth_login(&login_id).await {
Ok(tokens) => tokens,
Err(e) => {
let _ = codex_oauth::clear_pending_login(&login_id); // avoid stuck state
return Err(format!("OAuth 完成失败,请重新发起登录: {}", e));
}
} Prevention
- Complete the OAuth flow in one sitting; don't leave the browser waiting
- Never restart the app between OAuth start and completion
- Avoid double-clicking the login button (duplicate login_ids)
- If it fails, always start a fresh login instead of retrying the completed call
When it happens
Trigger: complete_oauth_login(login_id) fails because the pending login expired or was never registered, the state token mismatched, the authorization code/token exchange with the Codex OAuth endpoint returned an error, or the callback server stored no result for that login_id.
Common situations: User took too long between starting login and completing authorization (pending state expired); user restarted the app between start and completed calls (in-memory pending login lost); clicking the login button twice so a stale login_id is completed; upstream auth server returning 4xx/5xx on token exchange.
Related errors
- Token 交换失败: status={}, body_len={}
- OAuth 回调服务器错误: {}
- Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s
- OAuth 流程失败: {}
- OAuth 回调服务器错误: {}
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/6c17a2f5ff97f57e.
Report an issue: GitHub.