Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Provider quota report cache never commits while Codex traffic flows, so every quota read re-probes Anthropic and drops its row on a single failed read

Chiusa
#7,956 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
48/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
backend

Direzione di ricerca

Read src/providers/quota/report-cache.ts and src/providers/quota.ts, then inspect the quota report cache tests. Trace how the Codex quota signature builds the cache key and how failed provider probes reuse prior rows. Add a regression test that changes only the Codex quota updatedAt between calls; done means the cache is reused and a transient failed probe preserves the Anthropic row.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

account-pool bug
Client or integration

Direct HTTP/API client (a desktop widget that called ocx provider quota --json every 60 s during these observations). The same path serves GET /api/provider-quotas.

Area

Proxy and routing (provider quota reports)

Summary

The 5-minute provider quota report cache (CACHE_TTL_MS in quota-wire.ts) is effectively disabled whenever the built-in ChatGPT forward provider is in pool mode and Codex requests are passing through the proxy. Every fetchProviderQuotaReports call therefore re-probes every provider upstream, including Anthropic's rate-limited /api/oauth/usage endpoint.

The cache key includes a digest of the Codex pool accounts' quota, and that digest includes updatedAt. Each proxied OpenAI response refreshes the main account's quota observation, so updatedAt changes every few seconds even when no percent or reset value changes. fetchProviderQuotaReports computes key before probing and commitKey after probing, and only commits when they match. While traffic is flowing they almost never match, so nothing is cached and the next call starts from scratch.

A second effect follows. Because previousCache.key === key is also false, previous is empty. When one provider probe returns null (a transient failure that should keep the last-good row), there is no last-good row to keep, and the provider disappears from the response entirely.

Expected: when only observation timestamps change, the cache commits and is reused for up to CACHE_TTL_MS, and a transient null probe keeps the bounded last-good row as the comments in quota.ts describe.

Reproduction
  1. Configure the built-in openai provider in forward/pool mode (so hasCodexPoolProvider(config) is true) plus an anthropic OAuth provider.
  2. Keep Codex requests flowing through the proxy (in our case Codex auto-review requests, model codex-auto-review, several per minute).
  3. Call ocx provider quota --json once per minute and record generatedAt, each report's updatedAt, and which providers are present.
  4. In parallel, watch ~/.opencodex/codex-quota-cache.json → quotas.__main__.updatedAt.

Observed:

  • quotas.__main__.updatedAt changed 9 times between 17:12:05 and 17:13:18 (KST), each about 2 s after an openai / codex-auto-review entry in usage.jsonl (17:12:03, 17:12:08–12, 17:12:25, 17:12:38–40, 17:13:00–02, 17:13:07, 17:13:16). Percent values did not change.
  • Every minutely response had generatedAt equal to the request time and a fresh openai updatedAt, so no response came from the cache.
  • Between 16:53 and 16:57, the anthropic row was missing from 4 of 5 responses. The account was Healthy and provider-account-quota-cache.json held a successful read from 16:58.
Root cause (code references, identical in 2.93.0 and dev 96e0e009e)
  • src/providers/quota/report-cache.ts:157 quotaSignatureValue() includes updatedAt: quota.updatedAt (line 166).
  • src/providers/quota/report-cache.ts:191 providerQuotaFromCodexQuota() sets updatedAt to Date.now() when the stored quota has none, which would also change the signature on every call.
  • src/providers/quota/report-cache.ts:197 cacheKeyWithAggregationState() hashes those signatures into the key (|codex-pool:<digest>).
  • src/providers/quota.ts:242 computes key before probing. :289 computes commitKey after probing. :329 commits only when commitKey === key.
  • src/providers/quota.ts:254 fast path and :267 previous both require currentCache.key === key, so neither the cache nor the last-good fallback applies.
Suggested fix
  1. Drop updatedAt from quotaSignatureValue() (and avoid the Date.now() fallback reaching the signature). The key would then change only when a presented value changes: percent, reset time, plan, paused, needsReauth or active account. Staleness stays bounded by CACHE_TTL_MS and LAST_GOOD_MAX_AGE_MS.
  2. Optionally, decouple last-good retention from the exact key: keep the previous row for a provider whose probe returned null as long as the provider set part of the key (cacheKey(config)) is unchanged.

If updatedAt is in the signature on purpose (for example, so the pooled openai aggregation refreshes after each observation), a coarser freshness bucket or a separate per-provider refresh for openai would avoid re-probing every other provider.

A regression test could call fetchProviderQuotaReports twice with a stub Anthropic probe, advance only the main Codex quota updatedAt between the two calls, and assert that the second call makes no upstream probe and still returns the anthropic row.

Version

@bitkyc08/opencodex 2.93.0 (installed). The same code is on origin/dev at 96e0e009e (2026-10-29).

Operating system

Windows (DisplayVersion 26H2)

Provider and model

anthropic (OAuth, /api/oauth/usage) and openai (built-in ChatGPT forward, pool mode)

Logs or error output
# service.log has no quota-probe entries: probeAnthropicUsageQuota returns { quota: null, failure } without logging.
# The HTTP status of the failed Anthropic usage reads is therefore not confirmed (429 suspected).
Redacted configuration
{
  "providers": {
    "openai": { "adapter": "openai-responses", "authMode": "forward" },
    "anthropic": { "adapter": "anthropic", "authMode": "oauth" },
    "xai": { "adapter": "openai-chat", "authMode": "oauth" },
    "google-antigravity": { "adapter": "google", "authMode": "oauth" }
  }
}
Checks
  • I searched existing issues and documentation. (Searched "quota cache key updatedAt", "cacheKeyWithAggregationState", "quota re-probe", "quota anthropic usage 429"; related but different: #6244, #6989.)
  • I removed secrets, tokens, account details, request credentials, and personal data.
Lingua principale
TypeScript
Stelle
16.9k
Fork
1.3k
Merge medio
16h 42m
PR unite (30g)
695

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di lidge-jun/opencodex

Tutte le issue di lidge-jun/opencodex

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.