stablyai/orca · warning · CodexResetCreditScopeRejection

accountRevisionChanged

accountRevisionChanged

Error message

The selected Codex account was updated before reset.

What it means

A CodexResetCreditScopeRejection with reason 'accountRevisionChanged'. The account record still exists but its updatedAt timestamp no longer matches expectedScope.accountRevision. The revision is part of the scope key, so any mutation to the account (re-authentication, email/identity refresh) invalidates an in-flight reset to prevent acting on stale identity.

Source

Thrown at src/main/codex-accounts/service.ts:566

        'The active Codex rate-limit target changed before reset.'
      )
    }

    const settings = this.store.getSettings()
    if (
      getSelectedCodexAccountIdForTarget(settings, expectedScope.target) !== expectedScope.accountId
    ) {
      throw new CodexResetCreditScopeRejection(
        'accountChanged',
        rateLimitState,
        'The selected Codex account changed before reset.'
      )
    }
    const account = settings.codexManagedAccounts.find(
      (candidate) => candidate.id === expectedScope.accountId
    )
    if (!account || account.updatedAt !== expectedScope.accountRevision) {
      throw new CodexResetCreditScopeRejection(
        'accountRevisionChanged',
        rateLimitState,
        'The selected Codex account was updated before reset.'
      )
    }
    const normalizedAccountTarget = normalizeCodexAccountSelectionTarget(
      getCodexSelectionTargetForAccount(account)
    )
    if (!sameRateLimitTarget(normalizedAccountTarget, expectedScope.target)) {
      throw new CodexResetCreditScopeRejection(
        'accountRuntimeChanged',
        rateLimitState,
        'The selected Codex account belongs to a different runtime.'
      )
    }

    const currentScope = buildCodexResetCreditExpectedScope({
      target: rateLimitState.codexTarget,

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Capture a fresh expectedScope from the current account (its new updatedAt) and start a new attempt.
  2. Avoid mutating the account (re-auth/edit) while a reset is in flight; serialize these operations at the UI layer.
  3. For fresh attempts, treat the rejectedBeforeProvider result as 'discard and re-trigger'.

Example fix

// before: replaying scope captured before a re-auth bumped updatedAt
service.consumeRateLimitResetCredit(key, oldScope) // rejects accountRevisionChanged

// after: rebuild scope carrying the new accountRevision
const account = service.listAccounts().accounts.find(a => a.id === id)!
const scope = buildCodexResetCreditExpectedScope({ target, account, limits })!
await service.consumeRateLimitResetCredit(crypto.randomUUID(), scope)
Defensive patterns

Strategy: validation

Validate before calling

// Recapture the account revision right before consuming.
const account = service.listAccounts().accounts.find(a => a.id === scope.accountId)!
if (account.updatedAt !== scope.accountRevision) {
  // rebuild scope with the new revision before calling
}

Try / catch

try {
  await service.consumeRateLimitResetCredit(key, scope)
} catch (error) {
  if (error instanceof CodexResetCreditScopeRejection && error.reason === 'accountRevisionChanged') {
    // rebuild scope from the current account.updatedAt
  } else throw error
}

Prevention

When it happens

Trigger: The account was updated (doReauthenticateAccount bumps updatedAt at service.ts:876, or any field changed) after the scope was captured but before the provider reset validates. The persisted account.updatedAt diverges from expectedScope.accountRevision.

Common situations: User re-authenticates the account while a reset is queued; the mutation queue runs the re-auth first, bumping updatedAt, so the reset's captured revision is now stale.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/ab4cebde7f8b7180. Report an issue: GitHub.