[Bug]: "Use this account next" accepts an account that the active quota threshold immediately rejects #4521
Description
Client or integration
OpenCodex dashboard
Area
Authentication and account pool
Summary
With the Quota strategy and an enabled usage threshold, the dashboard still offers Use this account next for an account whose displayed quota is already above that threshold. The action accepts the selection and shows it as pinned, but routing releases the drained pin before resolving the next request and uses another eligible account.
The action therefore promises an outcome that the current routing policy will not allow. The setting responsible for overriding the action is also difficult to discover in the Providers workspace: Rotation strategy is visible, while the active usage threshold is only shown after expanding Advanced settings below it.
For example, with Main at 100%, a secondary account below the 80% threshold, and the secondary account currently selected, clicking Use this account next on Main does not make Main serve the next request. The pin is discarded because Main has no quota headroom.
Reproduction
- Configure two ChatGPT/Codex accounts in Pool mode.
- Select the
Quotarotation strategy and enable usage-based proactive switching with an 80% threshold. - Let Main reach 100% of its five-hour quota while the second account remains below 80%.
- Open Providers, select OpenAI, and view Available accounts.
- Observe that the visible strategy says
Quota, but the active80%threshold is only available inside the collapsedAdvanced settingssection. - Click
Use this account nexton the exhausted Main account. - Observe that the selection is accepted and pinned.
- Send the next request. Routing clears the Main pin as drained and selects the eligible secondary account.
The same mismatch is visible in current source. The account-card action is gated by pause, authentication, cooldown, and validation state, but not by known quota headroom. releaseDrainedCodexAccountPin() then clears the accepted pin when hasCodexQuotaHeadroom() is false.
Version
Observed with 2.53.0. The same action, collapsed-threshold layout, and drained-pin release are present on current dev at df7dc1be530141c55bd10e70ebe79cb80914d98e (package version 2.54.0).
Operating system
Ubuntu 24.04 under WSL2
Provider and model
OpenAI ChatGPT/Codex account pool; model-independent
Logs or error output
accountPoolStrategy=quota
autoSwitchThreshold=80
main five-hour usage=100
secondary five-hour usage<80
manual pin accepted for main
next request resolves to secondary after the drained main pin is releasedScreenshots and supporting files
No private screenshot is attached. The visible state is described above without account email addresses or identifiers.
Redacted configuration
{
"accountPoolStrategy": "quota",
"autoSwitchThreshold": 80,
"codexAccountMode": "pool"
}Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Related: #504 made manual selection immediate while preserving known threshold rotation, and #806 clarified strategy-dependent threshold semantics. This report is narrower: the current dashboard still enables a manual action whose promised next-request outcome is impossible under the displayed quota state, while hiding the overriding threshold from the normal Providers view.
Possible observable fixes include disabling the action for an account known to be drained, warning in the confirmation that the pin will be released, and showing an effective policy summary such as Quota · 80% next to the visible rotation strategy. CURRENT, SELECTED, and PINNED should also expose their distinct meanings without requiring source knowledge.
Activity
lidge-jun commentedon Sep 13, 2026
리뷰 · 우선순위 66 / 80
이 이슈는 Quota 로테이션 + usage threshold가 켜져 있을 때, 대시보드의 “Use this account next”(i18n
codexAuth.setAsNext, 한국어 “이 계정을 다음에 사용”)가 이미 threshold를 넘긴 계정에도 눌러지고 핀까지 받아 준 뒤, 다음 요청 직전에 라우팅이 그 핀을 drained로 버려 다른 계정으로 가는 UX 거짓말입니다. 재현 시나리오(Main 100%, secondary <80%, strategy Quota, threshold 80)가 제품 언어로 잘 적혀 있고, 숨겨진 Advanced settings 때문에 사용자가 왜 핀이 무시되는지 더 알기 어렵다는 관찰도 맞습니다.현재
dev(HEADdf7dc1be5, 2.54.0)에서도 같은 구조입니다. GUIgui/src/components/CodexAccountPool.tsx의 setAsNext 액션은 pause/auth/cooldown/validation 쪽 게이트를 보고, 알려진 quota headroom으로는 버튼을 끄지 않습니다. 핀은src/codex/auth-api.ts→setCodexAccountPin으로 남고, 라우팅src/codex/routing.ts의releaseDrainedCodexAccountPin이hasCodexQuotaHeadroom이 false면 핀을 지웁니다. 즉 “다음에 이 계정”을 약속한 UI와 “threshold 밖이면 핀 무효”인 라우터가 서로 다른 진실을 말합니다. #504(수동 선택 즉시성)와 #806(strategy별 threshold 의미)의 후속 좁은 보고로 보는 본문 정리도 타당합니다. types/config 분할과는 무관합니다.제품 우선순위는 “데이터가 틀렸다”보다 “운영자 행동이 무시된다” 쪽에 가깝습니다. 라우팅이 안전한 쪽(헤더룸 있는 계정)으로 가는 건 맞지만, 대시보드가 불가능한 약속을 받아 주면 신뢰가 깎입니다. 본문이 제안한 관찰 가능한 수정(drained면 버튼 비활성, 확인에 핀 해제 경고,
Quota · 80%요약, CURRENT/SELECTED/PINNED 의미 노출)은 방향이 좋고 범위도 쪼갤 수 있습니다.라인 -
gui/src/components/CodexAccountPool.tsxsetAsNext 액션 - quota headroom/threshold를 enable 조건에 넣지 않는다. exhausted Main에도 클릭 가능하다.라인 -
src/codex/routing.tsreleaseDrainedCodexAccountPin/hasCodexQuotaHeadroom- 수락된 핀을 다음 선택 전에 버린다. UI 약속과 서버 정책이 어긋나는 지점이다.경로/심볼 -
gui/src/components/CodexPoolStrategySetting.tsx+ Advanced threshold - strategy는 보이는데 유효 threshold는 접힌 영역에 있어 원인 발견이 어렵다.경로/심볼 -
codexAuth.setAsNext/ PINNED 배지 - 핀이 곧 해제될 계정에도 성공 상태로 보인다.경로/심볼 -
#504/#806- 중복이 아니라 수동 핀 vs proactive threshold의 정합성 구멍으로 연결해 두는 게 맞다.메인테이너의 판단이 필요한 지점
Quota · 80%)을 Providers 기본 면에 항상 보여줄지너의 추천
bug/account-pool로 유지하고, 먼저 GUI에서 known-drained면 setAsNext를 비활성(또는 확인 문구에 즉시 해제됨을 명시)하는 작은 PR을 받는다. 라우팅의 drained-pin release는 안전망으로 남겨 두라. threshold 요약 노출은 같은 PR 또는 바로 다음 UX PR로 묶어도 된다.이 댓글은 grok-bot이 작성했습니다
feat(account-pool): display threshold summary with strategy and warn …
feat(account-pool): display threshold summary with strategy and warn …
feat(account-pool): display threshold summary with strategy and warn …
lidge-jun commentedon Sep 16, 2026
Tracking: draft PR #4567 covers this together with #4524.
Still present on
dev: the switch button gate atgui/src/components/codex-account-pool-cards.tsx:79-120does not consult the quota threshold that later rejects the account.fix(codex): report the pin routing will release instead of a bare acc…
lidge-jun commentedon Sep 17, 2026
Confirmed still reproducing on
dev@61ee64747b, and the two halves of it have different owners.The mechanism, for the record: the card action is gated on pause, plan exclusion, reauth, cooldown, validation and current selection but never on quota (
gui/src/components/codex-account-pool-cards.tsx:79);PUT /api/codex-auth/activevalidates existence, pause and pending validation, writes the pin unconditionally (src/codex/account-priority.ts:75) and answers a bare200withappliesImmediately: true; then the first resolve afterwards runsreleaseDrainedCodexAccountPin, finds!hasCodexQuotaHeadroom, and clears and persists the removal (src/codex/routing.ts:455). Nothing between those two steps tells the operator.The dashboard half -- which is what this issue is filed against -- is #4567 by @maoxin1234. It implements two of the three fixes suggested here, the confirmation warning and the
Quota · switch at 80%summary beside the visible strategy. That is the PR that should close this issue and #4524. It is currently a draft 88 commits behinddevawaiting its readiness checklist.The non-dashboard half is #4970.
ocx account useand the management API had the same contradiction with no warning of any kind: the CLI printed "auto-switch (threshold 80%) may override this pin" whether or not the pin was already spent, so the one case needing a definite sentence got the same hedge as the healthy case. That PR extractscodexAccountPinDrainReasonout of the release so there is one predicate rather than a copy per surface, has the route reportpinDrainedwith a reason when the next resolve would drop the pin it just recorded, and has the CLI state it. It claims neither issue and touches no file #4567 touches.On the choice between disabling the action, refusing the pin, and surfacing the conflict: surfacing is the right one. Honouring the pin over the threshold would change routing policy and deliberately send into a measured exhausted window, and refusing would turn a proactive 80% threshold into a hard capacity limit on a reading that can be stale. Note also that the warning must not be suppressed under round-robin: ordinary round-robin assignment ignores the threshold, but a manual pin's lifetime does not, which
tests/codex-integration/codex-pool-rotation.test.ts:941pins explicitly.One thing worth flagging for whoever reviews #4567: it necessarily recomputes the usage score in the browser to decide whether to warn, which can drift from
src/codex/routing/cooldown-math.tsaround Free/Go plans and short-window freshness. The server-projectedpinDrainedfield in #4970 is the value that removes that duplication if the GUI later wants it.fix(codex): report the pin routing will release instead of a bare acc…
fix(codex): report the pin routing will release instead of a bare acc…
feat(account-pool): show what the usage threshold means per strategy (#…
lidge-jun commentedon Sep 18, 2026
Fixed via #4982 at 302c4c3 (carry of #4567). Manual switch to a threshold-rejected account now warns before it happens.