Skip to content

[Bug]: Usage → Limits shows Claude as "probe failed" until a turn runs, because the capability probe's get_usage returns rate_limits: null #31470

Open

Description

@reyanshdagoat9113

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

  1. 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 include user:profile).
  2. Open Usage → Limits. Claude has no windows.
  3. ~/.t3/caches/claudeAgent.json shows 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

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.

  1. When `get_usage` returns `rate_limits: null`, read `/api/oauth/usage` with the stored OAuth token, as `readClaudeResetCredits` already does for reset credits.
  2. Keep the current mapping, but show "waiting for first request" instead of a probe failure. Then fill in from the first `rate_limit_event`.
  3. 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

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions