Skip to content

Muse tierLimit 429 shows "Usage limit reached" and offers Resume at reset while Muse's own usage report says 20% used #27096

Open

Description

@AngeloTadeucci

Note

Claude Opus 5.5 responding on behalf of Ângelo.

What happened

A long Muse thread kept failing with "Usage limit reached. Retry after 20:24." The user retried and got the same error. Meanwhile muse usage showed the 5-hour window at 20% and the weekly allowance at 45%, so the label and the suggested remedy did not match the account's actual state.

Diagnosis

T3's Muse adapter treats every failure that carries error.quota as usage_limit, titles it "Usage limit reached", and offers "Resume at reset" at quota.resetsAtMs. That holds even when the latest usage/changed report from the same host shows no window at 100%.

  • MuseTurnCompleted.error in packages/provider-muse/src/server/protocol.ts decodes only message and quota.resetsAtMs. Muse also sends quota.limitKind, here "tierLimit", and retryable, here false. Both are dropped before classification.
  • In packages/provider-muse/src/server/adapter.ts, usageLimited is true whenever quota !== undefined. museUsageLimitResetAt in usageLimits.ts reads latestSubscriptionUsage but only adds windows at 100% or more, so it falls back to quota.resetsAtMs and never surfaces the contradiction.
  • The test "limits a stop Muse types as quota at the reset it reports" in adapter.test.ts pins limitKind: "tierLimit" to usage_limit and checks only the reset time.

Muse's MSP schema, exported with muse schema generate-json-schema, says TurnError.quota is present iff the stopping failure was the quota class, and that clients branch on its presence. LimitKind is an open enum whose only current value is tierLimit. So keeping the usage_limit class, which makes the run resumable per #16288, follows the contract. What is wrong is the user-facing label and the recovery offer when T3's own usage data contradicts them.

The misleading "Subscription quota exhausted" text originates with Meta. Muse's local journal records the same refusal as error_kind: "tier_limit". That part is being reported to Muse separately.

Suggested direction: keep limitKind and retryable in the schema. When quota is present but latestSubscriptionUsage shows every window under 100%, use neutral wording such as "Muse refused this request", show the provider message and the usage reading, and do not present "Resume at reset" as the fix.

Steps to reproduce

No deterministic repro. It needs a Muse session that Meta refuses with a quota-class error while the subscription window still has room. Here it was a long muse-wonder-full-1.0 thread at about 315k prompt tokens across 885 messages, well under the model's 1,007,997-token context limit. On the same account and window, a one-line muse exec on the same model and route succeeded at 19:17Z, between two refusals of the long thread.

  1. Run a Muse thread until a turn fails with turn/completed carrying error.quota.
  2. Compare it with the most recent usage/changed event in the provider event log.
  3. Look at the failure item title and the recovery banner.

Version

0.1.4-nightly.20261028.3841

Environment

Linux x86_64, Ubuntu 26.04, T3 headless server via t3 serve, Muse Code 1.4.14-R7309.1

Evidence

# provider event log for the thread, native events
[2026-10-29T19:12:55.715Z] usage/changed  {"weekly":{"usedPercent":45,...},"window":{"resetsAtMs":1793316262000,"usedPercent":20,"windowDurationMins":300}}
[2026-10-29T19:18:02.479Z] turn/completed {"terminal":"failed","error":{"kind":"modelError","message":"API error 429 [request_id=e59387f3-bc74-41a0-aaa8-594279952249]: Subscription quota exhausted. Your usage window resets at 2026-10-29T23:24:22Z. (rate_limit_error)","quota":{"limitKind":"tierLimit","resetsAtMs":1793316262000},"retryable":false}}

# muse local tracing, same refusal
event="provider_stream.terminal" terminal="failed" reason="rate_limited" http_status=429 request_id="e59387f3-..." bytes_read=0 wire_events_seen=0

# muse usage --json, same minute
{"window":{"resetsAtMs":1793316262000,"usedPercent":20},"weekly":{"usedPercent":45},"reason":null}

Refusals of the same shape at 19:12:55Z, 19:18:02Z and 19:31:27Z. Each came back about 5 seconds after the request.

Related issues

#24885 is the same mislabel for Codex and OpenCode. It is not a duplicate: there, Codex discards the upstream reason before T3 sees it, while here Muse delivers a typed limitKind and retryable that T3's schema drops, and T3 already holds a usage report that contradicts the label. #18235, Muse usage never showing in Usage → Limits, is related but different.

Fix applied or workaround

None on the machine. The work moved to a fresh thread on another provider. The blocked thread is still blocked.

Filed by

claude, Opus 5.5, investigating by hand, not via t3 triage

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