stablyai/orca · warning · CodexResetCreditScopeRejection
offerUnavailable
offerUnavailable
Error message
The Codex reset-credit offer is no longer available.
What it means
A CodexResetCreditScopeRejection with reason 'offerUnavailable'. validateResetCreditScope was called with requireCurrentOffer=true (fresh attempts only) and buildCodexResetCreditExpectedScope returned null for the current state — meaning no reset-credit offer is currently available for this account/target/limits combination. The reset is refused before reaching the provider because there is no valid offer to consume.
Source
Thrown at src/main/codex-accounts/service.ts:591
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,
account: this.toSummary(account),
limits: rateLimitState.codex
})
// Why: a same-key replay resolves an already-started provider mutation;
// its credit snapshot may have refreshed, but its account/runtime identity may not change.
if (requireCurrentOffer && !currentScope) {
throw new CodexResetCreditScopeRejection(
'offerUnavailable',
rateLimitState,
'The Codex reset-credit offer is no longer available.'
)
}
if (
requireCurrentOffer &&
currentScope &&
resetScopeKey(expectedScope) !== resetScopeKey(currentScope)
) {
throw new CodexResetCreditScopeRejection(
'offerChanged',
rateLimitState,
'The Codex reset-credit offer changed before reset.'
)
}
return { managedHomePath: account.managedHomePath, rateLimits: rateLimitState }View on GitHub (pinned to 1136503c6a)
Solutions
- Refresh rate-limit state and only offer the reset action when buildCodexResetCreditExpectedScope returns a non-null scope.
- If the offer reappears, re-trigger a fresh attempt with a new idempotency key.
- Treat the rejectedBeforeProvider result as user-facing 'no reset available right now'.
Example fix
// before: firing a reset without checking an offer exists
service.consumeRateLimitResetCredit(uuid(), scope) // may reject offerUnavailable
// after: gate the UI on a live offer
const offer = buildCodexResetCreditExpectedScope({ target, account, limits: rateLimits.codex })
if (!offer) { show('No reset offer available'); return }
await service.consumeRateLimitResetCredit(crypto.randomUUID(), offer) Defensive patterns
Strategy: validation
Validate before calling
// Only offer a reset when a live offer exists.
const limits = rateLimits.getState().codex
const offer = buildCodexResetCreditExpectedScope({ target, account, limits })
if (!offer) { show('No reset offer available'); return }
await service.consumeRateLimitResetCredit(crypto.randomUUID(), offer) Type guard
const hasResetOffer = (scope: CodexResetCreditExpectedScope | null): scope is CodexResetCreditExpectedScope => scope !== null
Try / catch
try {
await service.consumeRateLimitResetCredit(key, scope)
} catch (error) {
if (error instanceof CodexResetCreditScopeRejection && error.reason === 'offerUnavailable') {
// no offer to consume; refresh and re-offer later
} else throw error
} Prevention
- Gate the reset UI on a non-null buildCodexResetCreditExpectedScope.
- Hide/disable the reset control while a rate-limit refresh is in flight.
When it happens
Trigger: Starting a FRESH reset attempt when the account/target is valid but the current rate-limit state carries no reset offer (e.g. quota already reset, offer window closed, or limits snapshot lacks a resettable offer). Replays (requireCurrentOffer=false) skip this check.
Common situations: User clicks 'reset' after the offer already lapsed; background rate-limit refresh removed the offer between the UI rendering the button and the click being processed; or the account has no eligible offer in the current limits.
Related errors
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/1c28cfaa8432098f.
Report an issue: GitHub.