Repository navigation
Second Claude account's usage never appears in the Limits tab — silently marked unsupported, never recovers #13053
Description
Activity
Triage
Verdict: Confirmed on
v0.0.42(719a76ca1) and currentmain(aff9318bf). Keep open. Not fixed by nightlies after 0.0.42 (including the cited0.0.43-nightly.20260919.1978). Not a duplicate of #12170. No later commit touchesclaudeUsageResponseToLimits/ theunsupportedlock inapplyUsageLimitsUpdate.This is a real server usage-limits bug. A second Claude instance can be permanently classified as
unsupportedafter the bootget_usageprobe, then silently omitted from Usage → Limits with no bar and no notice — even while mid-turnrate_limit_eventdata proves the account has real subscription windows.What you reported
Two Claude provider instances, separate Anthropic accounts, each with its own
homePath/CLAUDE_CONFIG_DIR. Only one ever appears under Usage → Limits. The other never gets a bar, warning, or error. Hitting a real rate limit on the missing instance surfaces utilization in a turn warning (five_hourat 109%,seven_dayat 45% forclaudeAgent_bagri), but Limits still shows nothing for it. Persists across days; refresh does not heal it.That matches the code.
What the code does
-
Probe →
unsupported.probeClaudeCapabilitiescalls the experimentalget_usageAPI per instance (with that instance’sCLAUDE_CONFIG_DIRfrommakeClaudeEnvironment).claudeUsageResponseToLimitscollapses both of these shapes tounavailable: { reason: "unsupported" }:if (!response.rate_limits_available || !response.rate_limits) { return { limits: makeUnavailableUsageLimits({ checkedAt, reason: "unsupported" }), ... }; }
So
rate_limits_available: false(API-key / Bedrock intent) andrate_limits_available: truewithrate_limits: null(transient fetch failure — the fix(claude): keep limits when the usage fetch fails #10597 shape) are indistinguishable. The raw probe body is not logged, so this report’s exact trigger is unconfirmed; either path yields the same lock. -
Limits UI hides
unsupportedcompletely.collectLimitAccountsskips any provider wherelimitsNotice(...) !== null. Forunsupported,limitsNoticereturns “This account has no subscription limits.”collectLimitNoticesthen explicitlycontinues pastreason === "unsupported", so that message never appears on the Limits tab either.- Net: no bar, no notice — silent disappearance.
-
Mid-turn data cannot recover.
applyUsageLimitsUpdatereturnspreviousunchanged whenprevious?.unavailable?.reason === "unsupported", on the assumption “an account that cannot have subscription windows will not start reporting them mid-turn.” The loggedrate_limit_event/runtime.warningforclaudeAgent_bagrifalsifies that for this instance: realfive_hour/seven_dayutilization is produced and then discarded. -
Re-probes re-lock.
resolveUsageLimitsAfterProbetreatsunsupportedas authoritative (it replaces published limits). Every successful probe that re-derivesunsupportedkeeps the instance buried. Unlike Claude usage limits: a rate_limit_event after a failed probe is published as a complete window list #12170’sprobeFailedpath, this does not self-heal on the 5-minute refresh.
homePathisolation itself is fine (ClaudeHome.ts/ adapter tests). The bug is classification + lock + silent UI skip, not config-dir mixing.Related, not duplicates
Work What it is Why this is separate #12170 / open #12700 Sparse rate_limit_eventafterprobeFailedpublished as a complete one-window listTransient / self-heals; different unavailablereason. This issue is a permanentunsupportedlock with no Limits row.Closed #10597 Map available: true+rate_limits: null→probeFailedinstead ofunsupportedWould help if that is the second instance’s probe shape. Closed (V2 freeze note); never landed. Does not cover a true available: falseon a subscription account. Landing it without #12170/#12700 would also widen the sparse-merge hole.Open #12799 Grok: false unsupported→ same silent Limits vanishSame UI/contract footgun, different provider mapper. Pattern confirmation, not a Claude fix. No open issue tracks “second Claude account stuck as
unsupportedand invisible on Limits.”Suggested fix
Keep this a small server (+ optional shared UI) bugfix. Do not invent a new limits protocol.
- Narrow
unsupportedinclaudeUsageResponseToLimits. Reserve it for accounts that can never report subscription windows (API key / Bedrock / Vertex). Maprate_limits_available: true+ missingrate_limitstoprobeFailed(the fix(claude): keep limits when the usage fetch fails #10597 distinction). If interactive OAuth / Max accounts can still returnavailable: falseunder a separateCLAUDE_CONFIG_DIR, treat that asprobeFailed(or log and investigate) rather than a permanent can-never-report mark. - Do not let a false
unsupporteddiscard mid-turn windows forever. Options (pick one, keep it small):- Allow
rate_limit_eventupdates to clear / demote a mistakenunsupported(then apply the Claude usage limits: a rate_limit_event after a failed probe is published as a complete window list #12170/fix(server): keep usage-limits incomplete after sparse post-probe updates #12700 incomplete-marker rules so sparse updates do not look complete), or - Stop treating probe-derived
unsupportedas irreversible when the same instance later emits utilization events.
- Allow
- Log the
get_usageshape (rate_limits_available, whetherrate_limitsis null) on the probe path so the next multi-instance report is not inferred. - UI (small, optional): for an authenticated Claude instance marked
unsupported, show a notice instead of the total omit incollectLimitNotices. True API-key accounts can stay muted; subscription-looking accounts should not vanish. - Tests: second-instance /
available:true+null→ not permanent silent omit;unsupported+ mid-turn{ id: "five_hour" }must not stay a black hole if you choose (2); existing API-key →unsupportedcase stays green.
Coordinate with #12700 so a probeFailed reclassification does not reintroduce weekly-only “complete” snapshots.
Do not treat “refresh Limits,” “wait for provider health,” or landing #10597 alone as the fix.
Workaround
None that restores the Limits row while the probe keeps returning the failing shape. Mid-turn rate-limit warnings still carry real utilization for that instance. Ensuring both instances are interactively signed in under their own
homePath(and that env overrides likeCLAUDE_CODE_OAUTH_TOKENare not pointed at the wrong account) is worth checking, but this report’s evidence already shows a live subscription on the missing instance.Classification: bug · accepted · medium (server usage-limits; multi-Claude-instance; permanent
unsupportedlock; silent Limits omit; related to #12170 / #10597 / #12799)-
- addedacceptedfeature request acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 22, 2026 Hit this with a single Claude instance (no second account, no
CLAUDE_CODE_OAUTH_TOKENoverride), and I can confirm whichget_usageresponse triggers it.Setup: T3 Code (Nightly) 0.0.46-nightly.20261003.2638, Claude Code CLI 2.1.288, Claude Team subscription, macOS 27.2. Usage → Limits only shows Codex. Claude isn't there at all, and there's no notice either.
What the CLI returns: I ran the same calls the capabilities probe makes (
initializationResult()and thenusage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET()) through@anthropic-ai/claude-agent-sdkagainst the same CLI binary:{ "subscription_type": "team", "rate_limits_available": true, "rate_limits": null }I got the same result with
settingSources: [], so it isn't caused by my user settings.So the account clearly has subscription limits (
rate_limits_available: true), butrate_limitsisnull. In the 2.1.288 bundle,rate_limitsis onlynullwhen the CLI's own usage fetch doesn't come back withstatus: "ok", e.g. an in-band error, a 429, or an empty body. In other words, the fetch failed on the CLI side. It doesn't mean the account has no limits.claudeUsageResponseToLimitstreats both cases the same way:t3code/apps/server/src/provider/Layers/claudeUsageLimits.ts
Lines 162 to 167 in 8d84666
if (!response.rate_limits_available || !response.rate_limits) { return { limits: makeUnavailableUsageLimits({ checkedAt, reason: "unsupported" }), names: { overageIncluded: undefined }, }; } and then
collectLimitNoticesskips"unsupported"without showing anything:t3code/packages/shared/src/usageLimits.ts
Lines 302 to 304 in 8d84666
// An account that can never report (API key) is left out; one that // failed, or reported nothing at all, is worth a line. if (provider.usageLimits?.unavailable?.reason === "unsupported") continue; Suggestion: only use
"unsupported"whenrate_limits_available === false. When it'struebutrate_limitsisnull, treat it asprobeFailed, so the user sees a notice, laterrate_limit_events aren't locked out, and the next probe can recover.Screenshots: the composer is on Claude Opus 5, and the Limits tab shows only Codex.

- added a commit that references this issue
on Oct 5, 2026 Confirmed one trigger for the silent
unsupported: a token fromclaude setup-tokenpassed throughCLAUDE_CODE_OAUTH_TOKEN.Same Claude Max account, same machine, same SDK probe T3 runs (
initializationResult()+usage_EXPERIMENTAL…()):auth account.subscriptionTypeget_usageCLAUDE_CODE_OAUTH_TOKENfromclaude setup-tokenundefined rate_limits_available: false/login(credentials file, scopes includeuser:profile)Claude Maxtrue, windows presentIt shows up as soon as T3 runs on a remote machine over SSH: the macOS keychain is locked in an SSH session, so a setup token is the usual way to sign Claude in there. The Limits tab then says "No provider on the selected environments reports subscription limits", while Tokens and Cost still work, so nothing points at the token.
Telling apart "no subscription" from "signed in with an inference-only token" would make this self-explanatory: the init result already reports
tokenSource: CLAUDE_CODE_OAUTH_TOKEN, so the Limits tab could say that limits need a fullclaude /logininstead of staying silent.
What happened
Two Claude provider instances are configured, each a separate Anthropic account, each with its own
CLAUDE_CONFIG_DIR(homePath). Only one of the two ever shows a bar in Usage → Limits. The second instance never appears there — no bar, no warning, no error — even though it's actively used and has hit its own real rate limits.Diagnosis
Traced through
apps/server/src/provider/Layers/claudeUsageLimits.ts(claudeUsageResponseToLimits) at commit719a76ca(tagv0.0.42):For the second instance, the boot-time
get_usageSDK probe evidently reportsrate_limits_available: false(inferred from client behavior — the raw probe response body isn't logged anywhere, so I could not confirm exactly which condition on that instance triggers it; the instance uses a distinctCLAUDE_CONFIG_DIRand also has aCLAUDE_CODE_OAUTH_TOKENenvironment override configured, but the reporter's actual sign-in for that instance was interactive, not token-based, so the trigger is unconfirmed). Whatever the trigger, once it fires, T3 marks the instance"unsupported"— the same bucket used for API-key accounts that genuinely have no subscription. That is silent by design in two places:collectLimitAccounts(packages/shared/src/usageLimits.ts) skips any provider whoseusageLimitscarries a notice, including"unsupported"— no bar drawn.collectLimitNoticesexplicitlycontinues pastreason === "unsupported"— no warning shown either.This traps the instance permanently:
applyUsageLimitsUpdate(apps/server/src/provider/providerUsageLimits.ts) refuses to apply later updates once a snapshot is marked"unsupported", on the assumption "an account that cannot have subscription windows will not start reporting them mid-turn." That assumption doesn't hold here — the provider event log shows genuine mid-turnrate_limit_eventdata from this same instance (five_hourat 109% utilization,seven_dayat 45%), proving the account does have real, trackable quota. That data is discarded on arrival because the snapshot is already locked to"unsupported".Net effect: a second Claude account with real subscription limits is indistinguishable, in this code path, from an account with no subscription at all, and disappears from the Limits tab with zero user-facing feedback — regardless of which auth method it used to sign in.
Checked upstream issue #12170, which covers a related but distinct bug (a transient
probeFailedstate after a failed boot probe, which self-heals within ~5 minutes via periodic refresh). This case doesn't self-heal — every fresh probe re-derives the same"unsupported"state, so it persists indefinitely across days of use. Not a duplicate.Steps to reproduce
homePath(separateCLAUDE_CONFIG_DIR).Version
0.0.42 (also confirmed present in the currently-running desktop build,
0.0.43-nightly.20260919.1978— no relevant commits landed between the two)Environment
Linux x64, Node v26.8.2, claude CLI 2.1.278
Evidence
Related issues
#12170 — related mechanism (probeFailed → sparse window merge), but transient/self-healing, unlike this permanent
"unsupported"lock. Not a duplicate.Fix applied or workaround
None found.
Filed by
claude (sonnet-5) via t3 triage