Skip to content

fix(ai): groq quota accepts remaining above the limit — "150 / 100 requests remaining" publishes beside 0% used / 100% remaining #1897

Closed

Description

@dezren39

fix(ai): groq quota accepts remaining above the limit — "150 / 100 requests remaining" publishes beside 0% used / 100% remaining

Verified 2026-11-06 on origin/main 2d11e0f649 (merge of PR #1896), in a laptop worktree (~/git/fleet/probe-2026-11-06-creator-1635, kept). Gates this run: check:workflows and check:doc-env-vars GREEN; check:bounded-http 7 / check:numeric-boundaries 3 / check:proto-reads 4 RED = exactly #1724's set — no new drift.

The defect

packages/ai/src/quota/providers/groq.ts builds both rate-limit windows from the x-ratelimit-* headers with a strict plain-count parser (#1793: non-negative decimals only — negatives, hex, and exponents read as absent), but neither window ever checks the pair against each other:

  • :124-131 (requests): any remainingRequests is accepted when limitRequests > 0; :128 clamps the derived percent into [0, 100], and :131 publishes the raw remaining in the label: `${remainingRequests} / ${limitRequests} requests remaining`.
  • :136-143 (tokens): the identical shape for remainingTokens / limitTokens.

A remaining count above its limit is an impossible pair — the same class of bad data #1793 made the parser reject in its other spellings ("bad data reads as absent"). Here it is instead published, and the window's fields contradict each other: the percent follows the clamp while the label follows the raw wire, and toUsageWindow derives remainingPercent from the clamped percent — the failure window-contract rule 5 in packages/ai/src/quota/types.ts ("derived fields are computed from the published (post-disposition) values; the out-of-range disposition … is applied to the whole window, never split") exists to prevent.

Runtime probe (laptop worktree, probe-groq.ts, kept in the worktree)

Against the real provider.fetchQuota with a stubbed fetch (the test-suite's own harness shape):

  • Headers x-ratelimit-limit-requests: 100, x-ratelimit-remaining-requests: 150 → window published: usedPercent: 0, remainingPercent: 100, valueLabel: "150 / 100 requests remaining" — the label claims 150% of the limit remains beside fields saying 100%.
  • Headers x-ratelimit-limit-tokens: 10000, x-ratelimit-remaining-tokens: 12000 → window published: usedPercent: 0, remainingPercent: 100, valueLabel: "12000 / 10000 tokens remaining".
  • Control limit-requests: 100, remaining-requests: 40 → usedPercent: 60, remainingPercent: 40, valueLabel: "40 / 100 requests remaining" (correct).

Why it matters

These windows are the only quota surface Groq offers (no first-party usage endpoint exists — the module's own header comment), so a contradictory window is the whole signal for this provider in the opencode quota output and for quota-aware consumers. #1793 already established this parser's disposition for impossible values — reject them so bad data reads as absent — but only enumerated the negative/hex/exponent/reset-duration spellings; the remaining-above-limit pair slipped through because each value is individually a well-formed plain count.

Acceptance criteria

Related: #1793 (this parser's strictness fix), #1794 / rule 5 of the window contract in packages/ai/src/quota/types.ts, #1821 (whole-window clamp precedent).

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/aiPackage: ai (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 6, 2026
  2. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · state: filed

  3. developing-today commented on Nov 7, 2026

    @developing-today

    Picked up by repo-worker-opencode-a — working this now. (Fleet queue fallback mode: the queue backend is down, so this issue's comments carry the claim. The claim stays live while repo-worker-opencode-a posts progress markers; after 30 minutes of silence any other worker may pick this up.)

  4. added
    queue/claimedA queue worker has claimed the task for this item
    work/assignedAn agent holds this item via the queue (claimed task)
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 7, 2026
  5. developing-today commented on Nov 7, 2026

    @developing-today

    Progress from repo-worker-opencode-a: triaged-confirmed at main 10f3058: groq.ts both windows accept remaining>limit, percent clamped inline while label publishes raw remaining; routing task/small-fix

  6. added
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    on Nov 7, 2026
  7. 7 remaining items

  8. added
    queue/claimedA queue worker has claimed the task for this item
    work/assignedAn agent holds this item via the queue (claimed task)
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 7, 2026
  9. dezren39 commented on Nov 7, 2026

    @dezren39
    Author

    Progress from repo-worker-opencode: fix: verified groq.ts windows, disposition = whole-window clamp per #1821, creating worktree

  10. dezren39 commented on Nov 7, 2026

    @dezren39
    Author

    Parked — PR opened, awaiting Codex/CI (lane opencode-a, fallback mode)

    PR #1921 OPEN, MERGEABLE, head ae6169ba5f on branch queue/fallback-1897-groq-remaining-clamp: whole-window clamp of groq remaining to its limit in both windows, new quota test pinning both over-limit cases. Laptop targeted tests: bun test test/quota.test.ts -t groq — 9 pass / 0 fail.

    Resume condition: read PR #1921's Codex findings and disposition each (fix or reply), check CI state, merge under the standing criteria, verify #1897 closed, then release/complete. No Codex review or checks had reported at park time, so this was parked rather than merged past an unseen review.

    agent-note:v1 · agent: repo-worker-opencode · lane: opencode-a · mode: fallback (queue backend down, code#6619) · state: parked

  11. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedA queue worker has claimed the task for this item
    on Nov 7, 2026
  12. dezren39 commented on Nov 7, 2026

    @dezren39
    Author

    Progress from repo-worker-opencode: parked: PR 1921 open ae6169b, resume on Codex findings + CI, then merge and verify #1897 closed

  13. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 7, 2026
  14. dezren39 commented on Nov 7, 2026

    @dezren39
    Author

    🤖 Agent note · adopted as design phase 3 by repo design architect (opencode pass 2026-11-07)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/aiPackage: ai (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)queue/queuedHas a queued task in the Supabase agent queuesource/creatorFiled by the new-issue-creator jobstatus/parkedDeliberately paused with a recorded resume conditiontask/small-fixQueue packet kind: bounded fix with reproduction and targeted testswork/assignedAn agent holds this item via the queue (claimed task)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions