jlcodes99/cockpit-tools · warning

CODEX_PENDING_OAUTH_ACCOUNT

CODEX_PENDING_OAUTH_ACCOUNT

Error message

CODEX_PENDING_OAUTH_ACCOUNT

What it means

refreshQuota refuses to call the backend for Codex accounts that are still in the pending-OAuth state (isCodexPendingOAuthAccount), throwing CODEX_PENDING_OAUTH_ACCOUNT. Quota cannot be refreshed until the OAuth flow completes and the account has real tokens.

Source

Thrown at src/stores/useCodexAccountStore.ts:388

    });
    await emitAccountsChanged({
      platformId: 'codex',
      reason: 'delete',
    });
    const nextCurrentAccountId = get().currentAccount?.id ?? null;
    if (previousCurrentAccountId !== nextCurrentAccountId) {
      await emitCurrentAccountChanged({
        platformId: 'codex',
        accountId: nextCurrentAccountId,
        reason: 'delete',
      });
    }
  },

  refreshQuota: async (accountId: string) => {
    const account = get().accounts.find((item) => item.id === accountId);
    if (account && isCodexPendingOAuthAccount(account)) {
      throw new Error('CODEX_PENDING_OAUTH_ACCOUNT');
    }
    try {
      return await codexService.refreshCodexQuota(accountId);
    } finally {
      await get().fetchAccounts();
      await get().fetchCurrentAccount();
    }
  },

  refreshSubscriptionInfo: async (accountId: string) => {
    const account = await codexService.refreshCodexSubscriptionInfo(accountId);
    await get().fetchAccounts();
    await get().fetchCurrentAccount();
    return account;
  },

  refreshAllQuotas: async () => {
    const successCount = await codexService.refreshAllCodexQuotas();

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Complete the OAuth authorization flow for the account before refreshing quota
  2. Check isCodexPendingOAuthAccount(account) in the UI and disable/defer quota refresh
  3. Re-trigger the account import/OAuth flow if it stalled
  4. Remove and re-add the account if the pending state is permanently stuck

Example fix

// before
await store.refreshQuota(accountId);
// after
const account = store.accounts.find(a => a.id === accountId);
if (account && !isCodexPendingOAuthAccount(account)) {
  await store.refreshQuota(accountId);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const account = store.accounts.find(a => a.id === accountId);
if (account && isCodexPendingOAuthAccount(account)) {
  // defer quota refresh until OAuth completes
}

Type guard

function isRefreshable(a?: CodexAccount): boolean {
  return !!a && !isCodexPendingOAuthAccount(a);
}

Try / catch

try {
  await refreshQuota(accountId);
} catch (e) {
  if ((e as Error).message === 'CODEX_PENDING_OAUTH_ACCOUNT') {
    // prompt user to finish OAuth authorization
  }
}

Prevention

When it happens

Trigger: Calling refreshQuota(accountId) for an account whose state is pending OAuth (imported mid-OAuth, OAuth flow started but never completed, or an account still awaiting authorization).

Common situations: User imported an account but never finished the browser OAuth consent; OAuth callback failed silently; account list refreshed mid-authorization and UI attempted a quota refresh.

Related errors


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