Client or integration
OpenCodex dashboard
Area
Authentication and account pool
Summary
A stored Codex pool account can retain a bearer whose JWT expiry is still in the future while the upstream service rejects that bearer after a subscription or account-plan transition. The account-list quota path calls WHAM with that bearer and immediately reports needsReauth: true on HTTP 401. It does not use the bounded stored-token recovery already used by the Responses/compact request path.
The expected behavior is one forced refresh for the rejected credential generation, followed by one WHAM replay with the rotated bearer. OpenCodex should require manual reauthentication only when the refresh grant or a structured WHAM response provides terminal revocation/expiry evidence. A bare second 401 should remain transient rather than being mislabeled as token expiry.
This is adjacent to, but not covered by, #2887/#2889: those changes recover Responses/compact requests. It is also distinct from #3003, which throttles repeated failed quota-prime calls without refreshing a WHAM-rejected pool bearer.
Reproduction
- Add a Codex-login account to the stored account pool and confirm that its refresh grant works.
- Change that account's subscription or plan in a way that causes the upstream service to rotate or reject the current access bearer while the stored JWT
exp remains in the future.
- Refresh the Codex authentication dashboard, or request
GET /api/codex-auth/accounts?refresh=1.
- Observe that the WHAM quota request returns HTTP 401 and the account DTO reports
needsReauth: true / token expired without attempting the stored-token forced refresh.
- Reauthenticate the same account manually and repeat the account-list request. The account works again and its current plan/quota can be read, showing that the previous classification was not proof that the refresh grant had expired.
Version
2.36.0; the missing recovery path was also confirmed on dev before the proposed fix.
Operating system
Windows 11 24H2
Provider and model
OpenAI Codex login; model-independent account quota lookup
Logs or error output
GET /api/codex-auth/accounts?refresh=1
WHAM quota lookup: HTTP 401
account result: needsReauth=true, quotaError=token_expired
Screenshots and supporting files
No attachment is required; the regression is covered with redacted in-process HTTP fixtures.
Redacted configuration
{
"codexAuth": {
"mode": "pool"
}
}
Checks
Client or integration
OpenCodex dashboard
Area
Authentication and account pool
Summary
A stored Codex pool account can retain a bearer whose JWT expiry is still in the future while the upstream service rejects that bearer after a subscription or account-plan transition. The account-list quota path calls WHAM with that bearer and immediately reports
needsReauth: trueon HTTP 401. It does not use the bounded stored-token recovery already used by the Responses/compact request path.The expected behavior is one forced refresh for the rejected credential generation, followed by one WHAM replay with the rotated bearer. OpenCodex should require manual reauthentication only when the refresh grant or a structured WHAM response provides terminal revocation/expiry evidence. A bare second 401 should remain transient rather than being mislabeled as token expiry.
This is adjacent to, but not covered by, #2887/#2889: those changes recover Responses/compact requests. It is also distinct from #3003, which throttles repeated failed quota-prime calls without refreshing a WHAM-rejected pool bearer.
Reproduction
expremains in the future.GET /api/codex-auth/accounts?refresh=1.needsReauth: true/ token expired without attempting the stored-token forced refresh.Version
2.36.0; the missing recovery path was also confirmed on
devbefore the proposed fix.Operating system
Windows 11 24H2
Provider and model
OpenAI Codex login; model-independent account quota lookup
Logs or error output
GET /api/codex-auth/accounts?refresh=1 WHAM quota lookup: HTTP 401 account result: needsReauth=true, quotaError=token_expiredScreenshots and supporting files
No attachment is required; the regression is covered with redacted in-process HTTP fixtures.
Redacted configuration
{ "codexAuth": { "mode": "pool" } }Checks