{"record":{"id":"7e1cecbdb9a31381","repo":"stablyai/orca","slug":"codex-reset-credit-attempt-state-is-inconsistent","errorCode":null,"errorMessage":"Codex reset-credit attempt state is inconsistent.","messagePattern":"Codex reset-credit attempt state is inconsistent\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/codex-accounts/service.ts","lineNumber":451,"sourceCode":"    })\n  }\n\n  private getPendingResetAttemptForAccount(\n    target: RateLimitRuntimeTarget,\n    account: CodexManagedAccount\n  ): { idempotencyKey: string; expectedScope: CodexResetCreditExpectedScope } | null {\n    const accountScopeKey = resetAccountScopeKey({\n      target,\n      accountId: account.id,\n      accountRevision: account.updatedAt\n    })\n    const idempotencyKey = this.unresolvedResetKeyByAccountScope.get(accountScopeKey)\n    if (!idempotencyKey) {\n      return null\n    }\n    const attempt = this.resetAttemptsByKey.get(idempotencyKey)\n    if (attempt?.state !== 'providerPending') {\n      throw new Error('Codex reset-credit attempt state is inconsistent.')\n    }\n    // Why: a durable providerPending attempt can only be resolved with its original key.\n    return { idempotencyKey, expectedScope: attempt.expectedScope }\n  }\n\n  private hasPendingResetForTarget(target: RateLimitRuntimeTarget): boolean {\n    return [...this.resetAttemptsByKey.values()].some(\n      (attempt) =>\n        attempt.state === 'providerPending' &&\n        sameRateLimitTarget(attempt.expectedScope.target, target)\n    )\n  }\n\n  private startResetCreditAttempt(\n    idempotencyKey: string,\n    expectedScope: CodexResetCreditExpectedScope,\n    attempt: CodexResetCreditAttempt\n  ): Promise<CodexResetCreditConsumeResult> {","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/codex-accounts/service.ts#L433-L469","documentation":"Thrown by getPendingResetAttemptForAccount when an idempotency key is present in unresolvedResetKeyByAccountScope but the corresponding attempt in resetAttemptsByKey is NOT in the 'providerPending' state. This is an internal invariant violation: the two maps must agree — a key is only tracked as 'unresolved' while its attempt is providerPending. It signals the reset-credit attempt bookkeeping fell out of sync, almost always due to ledger corruption or a bug in the persist/hydrate path rather than caller error.","triggerScenarios":"Reached only via consumeCurrentRateLimitResetCredit (service.ts:386) when an account is selected and getPendingResetAttemptForAccount is called. Fires when unresolvedResetKeyByAccountScope holds a key whose attempt state is 'fresh' or 'settled' (or is missing entirely from resetAttemptsByKey).","commonSituations":"Manual edits to the persisted CodexResetCreditAttemptLedger, a partially-failed persistResetAttempt that updated one map but not the other, or a version-skew between app releases that changed the state model while old ledger entries were rehydrated.","solutions":["Treat as a bug, not a usage error: collect the ledger contents and resetAttemptsByKey/unresolvedResetKeyByAccountScope state and report it.","Clear/reset the corrupt durable ledger so hydrateResetCreditAttempts rebuilds a consistent in-memory state (note this loses pending-attempt reconciliation for genuinely in-flight resets).","Audit recent changes to persistResetAttempt (service.ts:638), the promise settle handlers (service.ts:525), and discardResetAttemptsForRemovedAccount (service.ts:671) for a map that is mutated without its pair.","Add a regression test asserting unresolvedResetKeyByAccountScope only ever contains keys whose attempts are providerPending."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await service.consumeCurrentRateLimitResetCredit()\n} catch (error) {\n  if (error instanceof Error && error.message === 'Codex reset-credit attempt state is inconsistent.') {\n    // internal invariant violation — report and offer to reset the ledger\n    reportInvariantViolation(error)\n    return\n  }\n  throw error\n}","preventionTips":["Never hand-edit the persisted CodexResetCreditAttemptLedger.","After app updates that change the attempt state model, clear/ migrate the ledger deliberately.","Treat this error as a bug report, not a recoverable runtime condition."],"tags":["codex-accounts","rate-limit-reset","invariant","internal-bug","ledger"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}