Repository navigation
Quota guard pauses capture on seven_day_overage_included "rejected" even though the request succeeded (15.3.0) #5182
Description
Summary
On 15.3.0 with Claude subscription auth, the quota guard pauses capture whenever the seven_day_overage_included rate-limit window reports status: "rejected" — even though the request itself succeeded on the normal weekly allowance. Every cooldown probe then succeeds, stores an observation, and immediately re-arms a 30-minute cooldown, so capture stays paused until the overage-included window resets (days), while the account has plenty of normal allowance left.
Environment
- claude-mem 15.3.0 (worker on Linux, bun), Claude Code CLI v2.1.312
CLAUDE_MEM_PROVIDER=claude,CLAUDE_MEM_CLAUDE_AUTH_METHOD=cli(Claude Code OAuth token, Max subscription)- Health endpoint rate limits at the time:
five_hour2%,seven_day52%,seven_day_overage_included= rejected
Evidence (worker log, one probe)
12:39:13.126 [SDK] Starting SDK query {sessionDbId=279, ...}
12:39:18.998 [SDK] [session-279] ← Response received (1498 chars) {promptNumber=71} <observation>
12:39:19.004 [DB] [session-279] STORED | ... obsCount=1 | obsIds=[15033]
12:39:19.012 [SDK] Aborting session for quota guard: quota:seven_day_overage_included rejected by provider {window=seven_day_overage_included, ...}
12:39:19.780 [SESSION] [session-279] Generator paused for quota; preserving buffered work {pendingCount=76}
The same sequence repeated at 11:37, 12:08 and 12:39 — each probe got a real response and stored an observation, then the guard aborted and re-armed quota-cooldown.json (until = armedAt + 30 min). Between probes:
Skipping generator start while the provider cooldown is active {provider=claude, window=seven_day_overage_included, ...}
Primary in quota cooldown and the quota fallback cannot serve; capture waits until it clears {primary=claude, fallback=claude}
SessionStart banner: "The memory observer's allowance on claude is used up … Claude rejected the request because its weekly overage-included usage allowance is exhausted."
Changing CLAUDE_MEM_MODEL does not help (the cooldown is per provider and the next event re-arms it), and neither does a restart.
Root cause
In the bundled worker-service.cjs the hard-rejection branch (minified OLe) treats status === "rejected" on any window as exhaustion:
function OLe(t,e){
if (e.status==="rejected" || t==="overage" && e.overageStatus==="rejected")
return {abort:!0, window:t, reason:`quota:${t} rejected by provider`, pause:{kind:"quota_exhausted", ...}}
}and g7 includes seven_day_overage_included in the windows it walks. For that window, "rejected" only means the included-overage pool is spent — the request is still served from the normal allowance (as the stored observation proves). The overage window already gets special handling via overageStatus; seven_day_overage_included needs the same kind of exception.
Workaround / suggested fix
Local one-line patch (applied to both the marketplace and cache copies), then clear ~/.claude-mem/quota-cooldown.json and restart the worker:
-function OLe(t,e){if(e.status==="rejected"||
+function OLe(t,e){if(e.status==="rejected"&&t!=="seven_day_overage_included"||After the restart, capture resumed immediately (new observation stored, no guard abort, no cooldown re-armed).
A more robust fix in source might be: only treat a window's rejected status as exhaustion when the request actually failed (no assistant response / an error result), or exclude informational windows like seven_day_overage_included from the hard-rejection branch while still letting the utilization thresholds apply.
Related: #5012 (different stale-entry wedge; its "smaller related observation" about overage/overageStatus is the same family as this one).
Activity
thedotmack commentedon Oct 29, 2026
Thanks @beckman55, confirmed on main.
providerRejectioninsrc/services/worker/RateLimitStore.ts:512-516treatsstatus: 'rejected'on any window as exhaustion, includingseven_day_overage_included, soClaudeProvider.ts:582-596aborts the session even when the observer's own request succeeded. That contradicts the window's own contract comment (RateLimitStore.ts:49-59): only the provider refusing the observer's request should stop it on that bucket.The fix is to ignore a
rejectedstatus onseven_day_overage_includedunless the request itself was refused, with a test that feeds a successful response carrying that header. Happy to help land a PR if you or anyone wants to take it.beckman55 commentedon Oct 29, 2026
Thanks for confirming. Here's a patch against
main(342dfe0) you can commit as-is. If you want to keep attribution, add this trailer to the commit:Change:
providerRejectionskipsseven_day_overage_included. That window's headers ride on every response of an account with the bucket, so arejectedstatus there can arrive on a request that succeeded. A request the provider actually refuses still pauses capture through the existing paths: quota-limit prose →ResponseProcessor(quota:observer_text), or a thrown quota error →ClaudeProvider(quota:unknown:quota_exhausted). Every other window'srejectedhandling is unchanged.Tests: replaces
aborts on a rejected overage-included weekly window(it asserted the buggy behavior) with:rejectedoverage-included snapshot from a successful response →{ abort: false }(fails onmain, passes with the patch)rejectedoverage-included window next to arejectedseven_day→ still aborts onseven_dayAll 14 test files that reference the quota guard /
RateLimitStore: 364 pass, 0 fail.tsc --noEmitis clean.Apply with
git apply 5182.patch:5182.patch
fix(worker): exclude seven_day_overage_included from quota guard hard…
MohamedFBoussaid commentedon Oct 30, 2026
Same false positive on the plain
overagewindow in 15.7.0, on an account without extra usage enabled.Environment
CLAUDE_MEM_PROVIDER=claude,CLAUDE_MEM_CLAUDE_AUTH_METHOD=cli(subscription, OAuth token from the credential store)overagewindow always reportsrejectedEvidence (worker log, three consecutive probes)
Every probe succeeds, then the guard re-arms a 30-minute cooldown.
quota-cooldown.jsonshows"window": "overage","auth": "subscription", and the user-facing message reads "Claude rejected the request because its extra-usage usage allowance is exhausted." Meanwhile the main CLI session on the same account keeps working on its normal allowance.Where it comes from in 15.7.0
providerRejectionaborts one.status === "rejected"for any window, and additionally ont === "overage" && e.overageStatus === "rejected". For an account without extra usage, theoveragebucket is permanentlyrejected, so the guard can never clear on its own.History on this install
Before 15.5.0 the only window that ever paused capture here was
seven_day(22 occurrences, all genuine).quota:overage rejectedappears only from 15.5.0 onwards (7 occurrences, all against a successful response).Suggested rule
Treat a
rejectedstatus onoverage(andseven_day_overage_included, as in the fix discussed above) as informational only. The observer should pause on these buckets only when its own request was actually refused by the provider.Workaround that works
CLAUDE_MEM_QUOTA_FALLBACK_PROVIDER=openrouter(orgemini) routes capture through the fallback while the cooldown is active, and the buffered observations drain.