{"record":{"id":"19f00b0d6ce0a681","repo":"jlcodes99/cockpit-tools","slug":"codex","errorCode":null,"errorMessage":"刷新 Codex 配额失败","messagePattern":"刷新 Codex 配额失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/commands/codex_account_commands.rs","lineNumber":1815,"sourceCode":"        return Ok(());\n    }\n    // 分组策略「不刷新」：自动当前号刷新静默跳过\n    if !codex_account::is_quota_refresh_enabled_for_account(&account.id) {\n        logger::log_info(&format!(\n            \"[Codex Quota] 当前账号所属分组已关闭额度刷新，跳过: account_id={}\",\n            account.id\n        ));\n        return Ok(());\n    }\n\n    let result = codex_quota::refresh_account_quota(&account.id).await;\n    if result.is_ok() {\n        run_codex_post_refresh_checks(&app).await;\n        let _ = crate::modules::tray::update_tray_menu(&app);\n        Ok(())\n    } else {\n        Err(result\n            .err()\n            .unwrap_or_else(|| \"刷新 Codex 配额失败\".to_string()))\n    }\n}\n\n/// 刷新所有账号配额\n#[tauri::command]\npub async fn refresh_all_codex_quotas(app: AppHandle) -> Result<i32, String> {\n    let results = codex_quota::refresh_all_quotas().await?;\n    let success_count = results.iter().filter(|(_, r)| r.is_ok()).count();\n    if success_count > 0 {\n        run_codex_post_refresh_checks(&app).await;\n    }\n    let _ = crate::modules::tray::update_tray_menu(&app);\n    Ok(success_count as i32)\n}\n\n/// 按账号 ID 列表限流并发刷新配额（分组刷新 / 本地访问批量等）\n/// 只在全部任务结束后做一次 tray / post-check，避免 N 次并发互踩。","sourceCodeStart":1797,"sourceCodeEnd":1833,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src-tauri/src/commands/codex_account_commands.rs#L1797-L1833","documentation":"In src-tauri/src/commands/codex_account_commands.rs:1815 the refresh-Codex-quota Tauri command maps a failed inner refresh result to Err, falling back to the literal \"刷新 Codex 配额失败\" (\"failed to refresh Codex quota\") when the underlying error is somehow None. The frontend receives this as the command's rejection value; the actual cause is whatever the inner refresh produced.","triggerScenarios":"The inner refresh routine returns Err (network failure reaching Codex quota endpoints, invalid/expired account token, backend returning non-success) — or returns Ok(false)-like empty Err — while refreshing a Codex account's quota from the UI.","commonSituations":"Codex auth token expired and needs re-login; offline or proxy/firewall blocking the quota API; Codex backend outage or rate limiting; stale account entry referencing a removed session.","solutions":["Re-authenticate the affected Codex account (re-run its login flow) to refresh the token, then retry quota refresh.","Check network connectivity/proxy settings and retry; verify the quota endpoint is reachable.","Read the full error string accompanying the message (the fallback literal means the real Err was lost) and log result.err() details upstream.","If it persists, refresh all accounts via the '刷新所有账号配额' command or restart the app to rebuild account state."],"exampleFix":"// before\nErr(result.err().unwrap_or_else(|| \"刷新 Codex 配额失败\".to_string()))\n// after\nErr(result.err()\n    .map(|e| format!(\"刷新 Codex 配额失败: {e}\"))\n    .unwrap_or_else(|| \"刷新 Codex 配额失败: 未知原因\".to_string()))","handlingStrategy":"try-catch","validationCode":"// Frontend pre-check before refreshing quota:\nconst accounts = await invoke('list_codex_accounts');\nif (!accounts.some(a => a.authenticated)) {\n  console.warn('No authenticated Codex account; refresh will fail');\n}","typeGuard":"function isRefreshResult(r: unknown): r is { ok: boolean; error?: string } {\n  return typeof r === 'object' && r !== null && 'ok' in r;\n}","tryCatchPattern":"try {\n  await invoke('refresh_codex_quota', { accountId });\n} catch (e) {\n  console.error('刷新 Codex 配额失败:', e); // log full payload, not just the fallback literal\n  await promptCodexReauth();\n}","preventionTips":["Re-authenticate Codex accounts before tokens expire.","Surface the full inner error string, not the generic fallback literal.","Retry with backoff on transient network failures; refresh all accounts after outages."],"tags":["rust","tauri","codex","api","quota-refresh"],"backgroundTag":"api-refresh-failed","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}