Keep limits available when usage history fails#6
Conversation
thrr87
left a comment
There was a problem hiding this comment.
Thanks for the contribution!
The overall direction looks good, and I verified that a well-formed usage RPC error no longer discards valid rate-limit data in either response ordering.
Before we can merge this, please address two protocol-state issues:
- Validate the usage error envelope before treating it as optional.
In CodexClient.swift, any present error value marks the usage request as finished. This accepts malformed envelopes such as:
{"id":3,"error":null}{"id":3,"error":"bad envelope"}
Both currently return a successful rate-limit snapshot with empty history. The PR description explicitly says malformed usage payloads should remain failures.
Please decode and validate a proper JSON-RPC error object - at minimum a numeric code and string message - and fail closed for invalid shapes.
- Keep initialization errors fatal.
An .initialize error currently reaches default: continue. If the server keeps the stream open, this turns a deterministic protocol failure into a misleading 15-second timeout.
Only a validated .usage RPC error should be non-fatal. Initialization and rate-limit errors should continue to fail immediately.
Please also add state-machine tests covering:
- a usage error received after the rate-limit response;
- malformed
errorvalues (null, a string, and objects missingcodeormessage); - initialization RPC errors.
Non-blocking: please use RequestID.initialize.rawValue in the initialize request as well, so the request-ID enum migration is complete.
The requested changes are about preserving strict protocol validation and avoiding an availability regression.
Keep limits available when usage history fails
Issue
Nature
Codex Limits can receive a valid current rate-limit response while the separate usage-history request fails. In that situation, the app shows “Codex returned data this app could not read” and keeps the user from seeing an otherwise valid remaining allowance.
Root cause
CodexClienttreated every JSON-RPC error as fatal and required bothaccount/rateLimits/readandaccount/usage/readto succeed before producing a snapshot.Those responses do not have equal importance:
account/rateLimits/readowns the current remaining allowance and reset window.account/usage/readsupplies historical token buckets used only to bootstrap forecasting.As a result, a transient failure in optional historical data incorrectly discarded the mandatory current-limit data.
How the fix solves it
The response state machine now distinguishes the two requests:
Request IDs are also represented by a private enum so the response routing documents its protocol meaning instead of relying on repeated numeric literals.
User impact
Users can continue seeing their current remaining allowance and reset time during a temporary usage-history outage. Historical forecasting starts without server-provided token buckets for that refresh and recovers naturally when a later refresh succeeds.