Repository navigation
Description
Area: apps/server
I searched existing issues. This overlaps with #30310, #15364 and #28852, so here is what this adds: a reproduction outside T3, the root cause, and what remains after the open PRs.
Steps to reproduce
- Windows 11, T3 Code nightly 0.1.8-nightly.20261104.4179, Claude Code CLI 2.1.318, Claude Pro, signed in with the OAuth login (
~/.claude/.credentials.json, scopes includeuser:profile). - Open Usage → Limits. Claude has no windows.
~/.t3/caches/claudeAgent.jsonshows the provider as ready and authenticated, but:
\"usageLimits\": { \"windows\": [], \"unavailable\": { \"reason\": \"probeFailed\" } }Cause
The capability probe (ClaudeProvider.ts, the usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true }) call) starts a Claude session and never sends a prompt. I sent the same control request straight to the CLI, outside T3:
{\"type\":\"control_request\",\"request_id\":\"r1\",\"request\":{\"subtype\":\"get_usage\",\"skip_behaviors\":true}}
| When the request is sent | Response |
|---|---|
| Right after startup | rate_limits_available: true, rate_limits: null |
| 6 s and 12 s later, still no prompt | rate_limits_available: true, rate_limits: null |
| After one tiny haiku message | rate_limits: { five_hour: { utilization: 4, ... }, seven_day: { utilization: 4, ... } } |
So it is not timing and not auth. In this CLI version rate_limits seems to be filled only from the response headers of a real API call in that session, so a probe that never sends a prompt always gets null. That is an inference from the three runs above. I did not test older CLI versions.
The login and the endpoint are fine: GET https://api.anthropic.com/api/oauth/usage with the same token and anthropic-beta: oauth-2025-04-20 returns HTTP 200 with five_hour and seven_day utilization.
claudeUsageResponseToLimits turns rate_limits_available: true plus rate_limits: null into probeFailed. That is the behavior chosen in #15364. It keeps Claude in the list, but there are no numbers.
Expected behavior
Limits are visible without first having to run a turn, or the UI says it is waiting for the first request rather than reporting a failure.
Actual behavior
On a fresh session Claude shows "probe failed" with no windows. Real turns stream rate_limit_events with usable numbers, but they were being dropped (see below).
The same session logs show those events carry no top-level utilization, only unifiedWindows:
\"rate_limit_info\":{\"status\":\"allowed\",\"resetsAt\":1793824800,\"rateLimitType\":\"five_hour\",\"overageStatus\":\"rejected\",\"overageDisabledReason\":\"org_level_disabled\",\"isUsingOverage\":false,\"unifiedWindows\":{\"five_hour\":{\"utilization\":0.03,\"resetsAt\":1793824800,\"status\":\"allowed\"},\"seven_day\":{\"utilization\":0.04,\"resetsAt\":1793966400,\"status\":\"allowed\"}}}Related work
- Claude usage limits never populate: rate_limit_event numbers live under unifiedWindows, and get_usage returns rate_limits: null #30310 reports both halves: dropped
unifiedWindowsevents and theget_usagenull. - [Bug]: Usage meter refreshes much slower than Claude Code's (separate from the 5h drain issue) #28852 is the triaged issue for the dropped events, with PR fix(server): Claude usage meter follows live rate-limit updates below the warning threshold #28869 as its fix. I checked the diff and it covers
five_hour,seven_dayand the overage-included row. - I opened fix(server): Claude limits update from rate_limit_event unifiedWindows #30999 for the same event mapping, then closed it in favor of fix(server): Claude usage meter follows live rate-limit updates below the warning threshold #28869. CodeRabbit's one finding on it, a flat `utilization` alongside `unifiedWindows`, is already handled in fix(server): Claude usage meter follows live rate-limit updates below the warning threshold #28869.
- [Bug]: Claude disappears from Usage → Limits when get_usage returns rate_limits_available: true with rate_limits: null #15364 (closed) triaged the null response and led to the current `probeFailed` mapping.
I believe #28869 does not cover this issue, because it only changes the per-event mapping. Its runtime test uses a stub that answers `/api/oauth/usage`, so it does not exercise the CLI returning `rate_limits: null`. I have not run #28869 against CLI 2.1.318, so I can't confirm the tab fills in after the first turn.
Possible directions
These are suggestions only; the right one is a maintainer call.
- When `get_usage` returns `rate_limits: null`, read `/api/oauth/usage` with the stored OAuth token, as `readClaudeResetCredits` already does for reset credits.
- Keep the current mapping, but show "waiting for first request" instead of a probe failure. Then fill in from the first `rate_limit_event`.
- Make the probe send a minimal prompt. I'd avoid this, since it spends tokens on every refresh.
Impact
Minor bug or occasional failure. The windows appear after the first turn once streamed events are mapped, but until then the tab reports a failure on an otherwise healthy login.
Activity