{"record":{"id":"73ed8d2636ee8a3d","repo":"stablyai/orca","slug":"a-previous-reset-attempt-for-this-target-still-has","errorCode":null,"errorMessage":"A previous reset attempt for this target still has an unknown outcome.","messagePattern":"A previous reset attempt for this target still has an unknown outcome\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/codex-accounts/service.ts","lineNumber":425,"sourceCode":"      if ('status' in result) {\n        throw new Error('The Codex account or reset offer changed before reset.')\n      }\n      return { outcome: result.outcome, state: result.rateLimits }\n    }\n\n    return this.serializeMutation(async () => {\n      if (this.resetLedgerLoadError) {\n        throw this.resetLedgerLoadError\n      }\n      const target = this.rateLimits.getState().codexTarget\n      if (!sameRateLimitTarget(target, initialTarget)) {\n        throw new Error('The active Codex rate-limit target changed before reset.')\n      }\n      if (getSelectedCodexAccountIdForTarget(this.store.getSettings(), target)) {\n        throw new Error('The selected Codex account changed before reset.')\n      }\n      if (this.hasPendingResetForTarget(target)) {\n        throw new Error('A previous reset attempt for this target still has an unknown outcome.')\n      }\n      const codexHomePath = this.runtimeHome.prepareForRateLimitFetch(target)\n      return this.rateLimits.consumeCodexRateLimitResetCredit({\n        idempotencyKey: randomUUID(),\n        target,\n        codexHomePath\n      })\n    })\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","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/codex-accounts/service.ts#L407-L443","documentation":"Thrown by the default/system-target branch of consumeCurrentRateLimitResetCredit (the path taken when no managed account is selected for the current runtime target). The guard hasPendingResetForTarget found a reset-credit attempt still in the 'providerPending' state for this same target, so the service refuses to start a second concurrent default reset. It exists because a pending provider mutation's outcome is unknown and launching a parallel reset could double-spend or corrupt the rate-limit credit ledger.","triggerScenarios":"Calling consumeCurrentRateLimitResetCredit() while a prior default-target reset attempt is still providerPending — e.g. the provider RPC is still in flight, OR the app restarted and hydrateResetCreditAttempts reloaded a providerPending attempt from the durable CodexResetCreditAttemptLedger (service.ts:612) without ever settling it.","commonSituations":"App crash / force-quit during a reset leaves a providerPending entry in the persisted ledger; on next launch every default reset is blocked until that entry is reconciled. Also seen when two UI surfaces (switcher + banner) both trigger a reset for the system-default target in quick succession.","solutions":["Wait for the in-flight provider mutation to settle, then retry consumeCurrentRateLimitResetCredit — once state flips to 'settled' the guard clears.","If the app restarted with a stuck providerPending attempt (provider call is gone), trigger a reconciliation / re-resolve of the durable attempt for that target, or switch the selected account so the account-scoped reset path is used instead of the default-target path.","If a removed account orphaned the pending attempt, confirm discardResetAttemptsForRemovedAccount ran (service.ts:671); removing then re-adding the account purges it.","As a last resort, inspect the CodexResetCreditAttemptLedger for stale providerPending entries for this target and reconcile them via the account-management flow."],"exampleFix":"// before: concurrent default-target resets\nservice.consumeCurrentRateLimitResetCredit() // throws [900] if one is pending\n\n// after: serialize/await default resets per target\nawait service.consumeCurrentRateLimitResetCredit()\n// surface 'a reset is already in progress' to the UI instead of re-invoking","handlingStrategy":"retry","validationCode":"// Avoid invoking a second default-target reset while one is pending.\nconst pending = [...service.listAccounts().accounts].length === 0 && /* default target */ true\n// Orca exposes no direct public probe; track in-flight default resets in the UI:\nif (defaultResetInFlight) { show('A reset is already in progress'); return }\nawait service.consumeCurrentRateLimitResetCredit()","typeGuard":null,"tryCatchPattern":"try {\n  await service.consumeCurrentRateLimitResetCredit()\n} catch (error) {\n  if (error instanceof Error && error.message.includes('unknown outcome')) {\n    // a prior default-target attempt is still pending; surface 'in progress' and retry after it settles\n    return { status: 'reset-in-progress' }\n  }\n  throw error\n}","preventionTips":["Serialize default-target reset triggers in the UI (disable the button while one is in flight).","On startup, reconcile any providerPending durable attempts shown in listAccounts before allowing new resets.","Never trigger a default-target reset from two UI surfaces simultaneously."],"tags":["codex-accounts","rate-limit-reset","idempotency","concurrency"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}