{"record":{"id":"35b4ff7d123b2dde","repo":"stablyai/orca","slug":"accountruntimechanged","errorCode":"accountRuntimeChanged","errorMessage":"The selected Codex account belongs to a different runtime.","messagePattern":"The selected Codex account belongs to a different runtime\\.","errorType":"exception","errorClass":"CodexResetCreditScopeRejection","httpStatus":null,"severity":"warning","filePath":"src/main/codex-accounts/service.ts","lineNumber":576,"sourceCode":"        rateLimitState,\n        'The selected Codex account changed before reset.'\n      )\n    }\n    const account = settings.codexManagedAccounts.find(\n      (candidate) => candidate.id === expectedScope.accountId\n    )\n    if (!account || account.updatedAt !== expectedScope.accountRevision) {\n      throw new CodexResetCreditScopeRejection(\n        'accountRevisionChanged',\n        rateLimitState,\n        'The selected Codex account was updated before reset.'\n      )\n    }\n    const normalizedAccountTarget = normalizeCodexAccountSelectionTarget(\n      getCodexSelectionTargetForAccount(account)\n    )\n    if (!sameRateLimitTarget(normalizedAccountTarget, expectedScope.target)) {\n      throw new CodexResetCreditScopeRejection(\n        'accountRuntimeChanged',\n        rateLimitState,\n        'The selected Codex account belongs to a different runtime.'\n      )\n    }\n\n    const currentScope = buildCodexResetCreditExpectedScope({\n      target: rateLimitState.codexTarget,\n      account: this.toSummary(account),\n      limits: rateLimitState.codex\n    })\n    // Why: a same-key replay resolves an already-started provider mutation;\n    // its credit snapshot may have refreshed, but its account/runtime identity may not change.\n    if (requireCurrentOffer && !currentScope) {\n      throw new CodexResetCreditScopeRejection(\n        'offerUnavailable',\n        rateLimitState,\n        'The Codex reset-credit offer is no longer available.'","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/codex-accounts/service.ts#L558-L594","documentation":"A CodexResetCreditScopeRejection with reason 'accountRuntimeChanged'. The account still exists with the same revision, but its selection target (getCodexSelectionTargetForAccount normalized) no longer matches expectedScope.target — i.e. the account itself now belongs to a different runtime/distro than the scope was built for. This catches a mismatch between the runtime the scope targeted and the runtime the account is actually persisted under.","triggerScenarios":"validateResetCreditScope recomputes the account's normalized target and compares via sameRateLimitTarget; a divergence (account moved host<->WSL, or distro changed in persisted data) triggers the rejection.","commonSituations":"Account data was edited/migrated so its persisted managedHomeRuntime/wslDistro no longer matches the rate-limit target that was active when the scope was captured. Rare in normal use; indicates a data migration or manual settings edit.","solutions":["Rebuild expectedScope against the account's actual persisted target (getCodexSelectionTargetForAccount).","Verify the account's managedHomeRuntime/wslDistro fields were not corrupted by a migration.","Discard the stale attempt and start fresh once the account/target are consistent."],"exampleFix":"// before: scope targets host but account is now persisted as WSL\nservice.consumeRateLimitResetCredit(key, scope) // rejects accountRuntimeChanged\n\n// after: derive the scope target from the account itself\nconst accountTarget = getCodexSelectionTargetForAccount(account)\nconst scope = buildCodexResetCreditExpectedScope({ target: accountTarget, account, limits })!\nawait service.consumeRateLimitResetCredit(crypto.randomUUID(), scope)","handlingStrategy":"validation","validationCode":"// Derive the target from the account itself rather than assuming it.\nconst accountTarget = getCodexSelectionTargetForAccount(account)\nconst scope = buildCodexResetCreditExpectedScope({ target: accountTarget, account, limits })\nif (!sameRateLimitTarget(accountTarget, scope!.target)) {\n  // account/runtime mismatch — do not consume\n}","typeGuard":null,"tryCatchPattern":"try {\n  await service.consumeRateLimitResetCredit(key, scope)\n} catch (error) {\n  if (error instanceof CodexResetCreditScopeRejection && error.reason === 'accountRuntimeChanged') {\n    // rebuild scope against the account's actual persisted target\n  } else throw error\n}","preventionTips":["Never reassign an account's managedHomeRuntime/wslDistro without removing and re-adding it.","Build scopes from getCodexSelectionTargetForAccount(account), not from an assumed runtime."],"tags":["codex-accounts","rate-limit-reset","scope-rejection","runtime","wsl"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}