Skip to content

Fix Codex OAuth rate limit reset handling#531

Merged
ericdallo merged 2 commits into
editor-code-assistant:masterfrom
itkonen:fix/codex-rate-limit-reset
Jul 15, 2026
Merged

Fix Codex OAuth rate limit reset handling#531
ericdallo merged 2 commits into
editor-code-assistant:masterfrom
itkonen:fix/codex-rate-limit-reset

Conversation

@itkonen

@itkonen itkonen commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Since a recent upgrade the, Codex sessions have started to stall randomly after finishing a step, for example a tool call.

There seems to be a bug in the way rate limits are read from the messages, and by default there's cap on the wait time. This PR should fix it.

AI Summary

Problem

ECA could put a ChatGPT/Codex OAuth session to sleep for hours after a 429 response. It inferred retry timing from apparently exhausted x-codex-primary-* and x-codex-secondary-* quota-window headers and selected the latest reset, while ignoring the authoritative reset in the response body. Because rateLimitMaxWaitSeconds was optional, that inferred delay was uncapped by default.

The behavior was checked against the official openai/codex implementation at commit f90e7deea6a715bbd153044af6f475eefa749177:

  • codex-rs/codex-api/src/api_bridge.rs handles a 429 usage_limit_reached response by reading numeric error.resets_at Unix epoch seconds from the JSON body.
  • The x-codex-* primary and secondary window fields are quota snapshots; they are not independently used as retry delays.
  • A generic 429 without usage_limit_reached follows the normal bounded retry path.

Fix

  • Read Codex OAuth error.resets_at only when error.type is usage_limit_reached.
  • Accept raw JSON bodies and already-decoded maps with string or keyword keys.
  • Keep retry-after as the highest-priority signal, while allowing expired higher-priority values to fall through to a usable future reset.
  • Stop treating Codex quota-window snapshot headers as retry instructions.
  • Preserve existing Anthropic and direct OpenAI reset-header handling.
  • Apply a default 60-second rateLimitMaxWaitSeconds cap to the total scheduled delay, including the existing one-second safety buffer; provider overrides remain supported.
  • Surface the provider reset timestamp immediately when the structured wait exceeds the cap.
  • Update the config schema and Unreleased changelog entry.

Verification

  • clojure -M:test --focus eca.llm-providers.errors-test — 9 tests, 83 assertions
  • clojure -M:test --focus eca.llm-api-test — 24 tests, 323 assertions
  • clojure -M:test --focus eca.llm-providers.openai-test — 21 tests, 75 assertions
  • LC_ALL=C bb test — 778 tests, 4,274 assertions, 0 failures
  • python3 -m json.tool docs/config.json — passed
  • git diff --check — passed
  • Tested manually with the local debug server and a Codex OAuth session.

clj-kondo was not available in the local environment.

  • I added a entry in changelog under unreleased section.
  • This is not an AI slop.

Use the authoritative usage-limit response reset and bound structured rate-limit waits so quota snapshot metadata cannot stall sessions for hours.

🤖 Generated with [ECA](https://eca.dev) (openai/gpt-5.6-sol - xhigh)

Co-Authored-By: eca-agent <git@eca.dev>
@itkonen itkonen marked this pull request as ready for review July 14, 2026 22:00

@ericdallo ericdallo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@ericdallo ericdallo merged commit 08ec1d0 into editor-code-assistant:master Jul 15, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants