Skip to content

[Bug]: Claude usage-limit reset shown in activity but missing auto-resume controls during subagent workflow #15665

Open

Description

@wobby13

Summary

A Claude thread using Orchestrator V2 subagents displays a reset time in its conversation activity, but the composer banner says Reset time unavailable; retry manually and offers no auto-resume or snooze controls. Another Claude thread in the same setup correctly displays the reset time and Cancel auto-resume / Snooze until reset.

Environment

  • macOS desktop client connected through T3 Connect to a macOS backend.
  • Custom build based on upstream nightly .2623, version 0.0.46-preview.20261003.1 (local commit 5c30ddb9). Customizations include reply suggestions and provider-inactivity UI. Not reproduced on an unmodified official build yet.
  • Claude Code subscription login; Orchestrator V2.
  • Observed 4 October 2026, Europe/London.

Observed sequence

  1. Run Claude work that delegates to multiple subagents.
  2. Exhaust the Claude subscription usage window.
  3. Activity shows a failed subagent and a Claude usage-limit warning with a reset countdown. Messages also say You've hit your session limit · resets 4:40pm (Europe/London) and Usage limit reached. Retry after 16:40.
  4. The same thread's composer shows Usage limit reached Reset time unavailable; retry manually, with no recovery scheduling actions.
  5. Another Claude thread shows a reset of 16:40 on the same date and exposes recovery controls, including Cancel auto-resume.

This is an observed case, not a deterministic minimal reproduction. Subagents were present, but they have not been established as the cause. A Waiting on subagent row also remained visible; this may be a separate state-display issue.

Expected behavior

When a trustworthy reset timestamp for the affected account and exhausted window is available, the failed turn should retain it and offer Resume at reset / Snooze until reset consistently. If only human-readable text is available and recovery cannot safely be scheduled, clearer explanation would help distinguish that from a thread/subagent failure. Do not guess a reset time or automatically enable recovery without the user's setting.

Investigation so far (not a confirmed root cause)

In the installed source, UsageLimitRecoveryBanner.tsx exposes scheduling actions only when a non-null reset time is later than the stop time. ClaudeAdapterV2.ts can emit a usage-limit failure with resetAt: null when its collected reset-time data is incomplete. That explains the UI condition, but we have not traced the raw SDK events for this particular failed run or established why its structured reset time is missing despite the displayed messages.

Related reports

Workaround / privacy

Manual retry after the subscription resets. No transcripts, private project names, account identifiers, or screenshots are included in this report.

Activity

  1. juliusmarminge commented on Oct 4, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the careful write-up, @wobby13, and for being upfront about the custom build and what you haven't confirmed yet. That made this much easier to look into.

    What I found

    The composer symptom also exists in unmodified source, both in nightly .2623 and on main at 4ee6bfd50e. Subagents don't appear to be required. This isn't a duplicate of #14169 or #13331.

    • How the banner decides. UsageLimitRecoveryBanner shows Reset time unavailable; retry manually and hides Resume at reset / Snooze until reset whenever the latest root error's failure.resetAt is null. That value comes from threadErrorSummary in packages/shared/src/orchestrationV2ThreadError.ts. The class is still usage_limit, which is why the title still reads "Usage limit reached".
    • How resetAt ends up null. ClaudeAdapterV2 sets failure.resetAt only when every recorded rate-limit window has a parseable resetsAt. One rejected window without resetsAt nulls the whole value, and so does an assistant rate_limit frame with no rejected events. The SDK text You've hit your session limit · resets 4:40pm is shown as provider text and isn't parsed into resetAt.
    • Why the activity can show a countdown anyway. Each rejected event that does include resetsAt emits its own per-window notice, so the activity can show a wait while the banner says the reset is unavailable. Your other Claude thread is most likely the case where every rejected window had a reset time.
    • "Retry after 16:40." In stock code, that work-log line only renders when that error item's failure.resetAt is set, so it can't come from the same root error the banner is reading. It probably belongs to an earlier error item or to your custom UI.
    • The leftover Waiting on subagent row. That comes from a separate surface (presentPendingBackgroundWork) and doesn't affect resetAt.

    Likely fix area

    • Options include deriving resetAt from the windows that do have a reset time, or using the latest known reset for the exhausted window, instead of the current all-or-nothing rule in ClaudeAdapterV2.
    • Another option is clearer banner copy when only provider text is available, so that case reads differently from a thread or subagent failure.
    • If you can share them, the failed turn's rate_limit_event frames (rateLimitType, status, resetsAt, overageStatus) would show exactly which window dropped its reset time.

    A maintainer will decide on the fix direction.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 4, 2026
  3. wobby13 commented on Oct 4, 2026

    @wobby13
    Author

    I checked the retained provider logs (including rotated files) and the V2 database read-only. Here is an allowlisted extract; thread/run labels below are arbitrary, and no conversation content, project names, paths, account details or session identifiers are included.

    Affected thread A

    Shortly before the failures, the retained SDK rate_limit_event.rate_limit_info was:

    {
      "rateLimitType": "five_hour",
      "status": "rejected",
      "resetsAt": 1791128400,
      "overageStatus": "rejected"
    }

    1791128400 is 2026-10-04 15:40 UTC / 16:40 Europe/London, matching the reset displayed in the report.

    Two successive persisted failed runs in this same thread differ:

    Observation Earlier failed run Following failed run (~10 seconds later)
    failure.class usage_limit usage_limit
    failure.code api_error_429 api_error_429
    failure.resetAt 2026-10-04T15:40:00.000Z null

    For the following run's requested-to-completed interval, the retained provider log contains an SDK frame with type: "assistant", error: "rate_limit", but no rate_limit_event frame. I am not substituting invented null values for its requested fields: there is no corresponding event from which to extract them. The interval is present in the log, including the assistant error frame immediately before completion.

    Comparison thread B

    The comparison thread's rejected event contains the same four allowlisted fields/values shown above. Its persisted failure has resetAt: "2026-10-04T15:40:00.000Z", consistent with its available recovery controls.

    What this narrows down

    For this specific occurrence, the evidence fits the assistant-rate-limit-without-a-new-rejected-event path, rather than demonstrating a rejected frame with a missing resetsAt. The known reset was present earlier in the affected thread, but the next failed run persisted null. This is a log/database observation, not proof of SDK delivery beyond what was retained, nor a deterministic reproduction.

    Your point about Retry after 16:40 belonging to an earlier error is consistent with the two successive stored failures: the earlier one has a reset and the later one does not. I have not independently mapped the screenshot's exact activity row to its stored item, so that identification remains an inference.

    No production settings were changed and no quota-consuming reproduction was run. This is still the custom build disclosed in the original report.

  4. coygeek commented on Oct 6, 2026

    @coygeek

    Additional investigated occurrence on a nightly macOS installation. I am the user's Codex agent, posting these sanitized findings with their authorization.

    Summary

    A Claude thread's first usage-limit failure retains a future structured reset, but two automatic background continuations immediately afterward fail with resetAt=null. The assistant text still reports the same reset, while the composer says Reset time unavailable; retry manually and there is no current saved snooze. This independently corroborates the known-reset-to-null sequence already reported here.

    Steps to reproduce

    1. The supplied incident had Auto-resume limited threads and Snooze limited threads enabled, with Claude work using background tasks.
    2. A five-hour limit notice reported a future reset, and the first inspected failed root turn stored that reset.
    3. Before the reset, two provider-origin, agent-created Background task completed messages started subsequent automatic continuation runs.
    4. Both subsequent root failures stored resetAt=null. The screenshot shows older reset information alongside the latest composer's missing-reset warning.

    These are supplied and reconstructed incident conditions, not a deterministic minimal recipe. No fresh quota-consuming reproduction was run. The exact raw SDK frames responsible for the null reset remain uninspected.

    Expected behavior

    With reset-aware recovery enabled, a continuation of the same exhausted window should retain trustworthy applicable reset information and consistent pause/recovery behavior. New provider information may invalidate a reset or add an unknown exhausted window; that case must not be handled by guessing a timestamp.

    Actual behavior

    Read-only V2 snapshots establish this sequence in one affected thread. All three root failures have class=usage_limit, code=api_error_429, and retryable=true. R below denotes the observed future timestamp; it is an anonymous label, not an invented replacement value in a raw log.

    Root failure Relative order failure.resetAt Initiating message, where included
    First inspected failure first known future R not included in this comparison
    Next failure less than one second later null Background task completed
    Following failure about 26 seconds after the next null Background task completed

    The assistant text on all three failures names the same human-readable reset. The affected thread's snoozedUntil and snoozedAt are null. Its retained limitRecovery references an earlier expired usage window, rather than its current failed run.

    A comparison thread also stores a known reset, then null on four successive failures, then the known reset again on a later failure. Its current recovery/snooze become valid and agree with the Snoozed sidebar presentation. This is one inspected incident; these sequence counts are not a population-frequency claim.

    Evidence

    • Expected source: The enabled reset-aware settings and the installed adapter's background-wake regression contract that reset-bearing wake information reaches the continuation failure.
    • Failure source: Observed read-only V2 root error items and provider-origin message metadata, corroborated by supplied composer/settings screenshots; the portable state sequence is reproduced above.
    • Evidence provenance: observed
    • Local verification: not-run
    • Reproduction completeness: incomplete
    • Missing fact: The exact raw SDK rate_limit_event and assistant error frames in the subsequent failed continuation turns, distinguishing a rejected event lacking resetsAt from no new rejected event arriving.

    Local verification means no new provider execution was attempted. The saved sequence was directly inspected. The null reset is established; the specific SDK path that produced it is not.

    The installed adapter starts a fresh per-turn reset map. Its terminal reset calculation yields null for an empty map or any unknown exhausted-window reset. It does not fill this map from human-readable reset text. The adapter also buffers pre-continuation rate-limit events, as expressed by its background-wake regression test, so this is not a claim that every background continuation drops reset metadata.

    Restoration check

    Replay the captured SDK sequence once available. A known future reset should remain applicable through a continuation of the same exhausted window when no conflicting, expired, or newly unknown window invalidates it. The following failed turn should expose consistent recovery controls and honor the enabled reset-aware pause. Keep invalidated/unknown resets and disabled recovery settings as controls; do not pass by guessing reset times or discarding background-task notifications.

    Runtime or environment

    The inspected macOS desktop and two installed servers report 0.0.46-nightly.20261005.2702; the installed package pins cfa4f76. Provider: Claude Agent SDK, Claude Opus 5.5. No live store or settings were changed during investigation.

    Triage assessment

    • Impact level: P2
    • Assessment status: supported
    • Impact basis: The inspected incident loses current reset-aware recovery metadata and requires attention to a paused Claude workflow. Data loss, universal reach, and actual behavior at reset are not established.
    • Workaround status: unverified
    • Workaround basis: The composer offers manual retry, but retry after reset was not exercised. Later restoration of metadata in the comparison thread is an observation, not a dependable workaround.
  5. bitconym commented on Oct 6, 2026

    @bitconym
    Contributor

    Another occurrence on 6 October 2026, with the redacted screenshot below. This matches the earlier report of a known reset disappearing on a subsequent Claude usage-limit failure:

    1. The earlier activity says the 5-hour limit resets in 3h 15m, and the error row says “Usage limit reached. Retry after 3:30 PM.”
    2. The following failure says only “Usage limit reached.”, even though the provider's text above it still explicitly says “your session limit resets 3:30pm.”
    3. The composer then shows “Reset time unavailable; retry manually”, leaving reset-aware auto-resume unavailable despite the earlier reset information.

    Both failures are shown at 12:15 PM in the screenshot. This is visual corroboration of the known-reset → missing-reset symptom; we have not inspected the raw SDK events or persisted failure fields for this occurrence, so we cannot establish which adapter path caused it. We have not tested #15697 locally.

    Earlier Claude failure shows Retry after 3:30 PM; the next failure loses the reset time and the composer requires manual retry

    Posted with the reporter's authorization by their Codex agent.

  6. EhsanulHaqueSiam commented on Oct 7, 2026

    @EhsanulHaqueSiam

    Root cause and a deterministic reproduction for the follow-up failures that lose resetAt. Verified on an unmodified official nightly (0.0.46-nightly.20261005.2702, Claude CLI 2.1.292, macOS) and on main at bfec2387b.

    No exhausted subscription is needed. The real CLI runs against a local mock of the Messages API that answers like a used-up five-hour window.

    Steps to reproduce (verified)

    1. Start the mock (mock-api.mjs, below) with a reset two minutes away:
      node mock-api.mjs 18787 $(( $(date +%s) + 120 ))
    2. Create fake-claude.sh, which runs the real CLI against the mock with a throwaway token and config dir:
      #!/bin/sh
      export ANTHROPIC_BASE_URL=http://127.0.0.1:18787
      export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-mock-not-a-real-token
      export ANTHROPIC_API_KEY=
      export CLAUDE_CONFIG_DIR=/tmp/t3-limit-claude
      export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
      exec claude "$@"
      It must use a subscription token: with an API key the CLI ignores the unified quota headers and the limit never registers.
    3. Write /tmp/t3-limit-home/userdata/settings.json, add a scratch project, and start an isolated dev server:
      {
        "autoResumeLimitedThreads": true,
        "snoozeLimitedThreads": true,
        "providerInstances": {
          "claudeAgent": { "driver": "claudeAgent", "enabled": true, "config": { "binaryPath": "/path/to/fake-claude.sh" } }
        }
      }
      node apps/server/src/bin.ts project add /tmp/t3-limit-project --base-dir /tmp/t3-limit-home
      vp run dev --home-dir /tmp/t3-limit-home
    4. In a new Claude thread in that project, send any message. It fails with Usage limit reached, and the banner shows Resets … with Cancel auto-resume.
    5. Within 30 seconds, send a second message in the same thread.
    6. Wait until the reset passes.

    Expected behavior

    The second failure keeps the reset, the banner keeps Cancel auto-resume, and the thread auto-resumes at the reset.

    Actual behavior

    • The second failure reads only Usage limit reached., and the banner changes to Reset time unavailable; retry manually.
    • Its root error stores failure.resetAt: null.
    • After the reset passes, nothing resumes. No limit-resume: message is dispatched and the mock receives no request.

    Measured on main, one thread:

    Turn Sent rate_limit_event in turn failure.resetAt
    1 0 s yes 2026-10-07T19:06:40Z
    2 +15 s none null
    3 +64 s yes 2026-10-07T19:06:40Z

    With the reset two minutes out, main had dispatched no limit-resume: message 40 s after the reset. With the fix below, the same steps kept the reset on turn 2, and Continue where you left off. was dispatched 2 s after the reset.

    In real use, the second limited turn usually starts by itself. A background task, subagent, or overdue ScheduleWakeup fires its wake turn the moment the limit ends the current turn, which matches the reports above. In my incident the wake turn came 1.5 s after the first limit hit.

    Root cause

    The CLI's headless stream does not send a rate_limit_event for every 429. It sends one when the limit state changes, and repeats an unchanged state at most once every 30 seconds for the same resetsAt. A limited turn that starts within 30 s of the last reported event, in the same CLI process, therefore gets no event.

    cli-throttle.mjs (below) shows this without T3, driving the CLI headless against the mock:

    +0.2s turn 1: rate_limit_event status=rejected resetsAt=1791400000
    +0.2s turn 1: result api_error_status=429 -> event SENT
    +1.2s turn 2: result api_error_status=429 -> event MISSING
    +36.2s turn 3: rate_limit_event status=rejected resetsAt=1791400000
    +36.2s turn 3: result api_error_status=429 -> event SENT
    

    ClaudeAdapterV2 takes the reset only from rate_limit_events seen during the turn, so that turn fails with resetAt: null. It becomes the thread's latest run and hides the earlier reset. UsageLimitRecoveryWorker skips any thread whose latest failure has no reset, even if it had already armed recovery for the earlier run.

    The reset is still on the blocked assistant message, in a field the SDK types omit. This is the incident's wake turn; every mock turn above, turn 2 included, carried the same field:

    {
      "type": "assistant",
      "error": "rate_limit",
      "api_error": "usage_limit_reached",
      "api_error_params": {
        "rate_limit_info": { "status": "rejected", "rateLimitType": "five_hour", "resetsAt": 1791324000, "overageStatus": "rejected" }
      }
    }

    That answers the triage question about this turn's frames: it has no rate_limit_event at all, but its root assistant frame names the window and reset.

    Possible fix

    Read api_error_params.rate_limit_info when the root assistant frame has error: "rate_limit". This works per turn with no cross-turn state, and an event-supplied reset still wins:

     if (message.parent_tool_use_id === null) {
       context.latestAssistantRateLimited = message.error === "rate_limit";
    +  if (message.error === "rate_limit" && isClaudeBlockedAssistantRateLimit(message)) {
    +    const info = message.api_error_params.rate_limit_info;
    +    const limitType = info.rateLimitType ?? "unknown";
    +    context.rejectedRateLimitTypes.add(limitType);
    +    context.rateLimitResetTimes.set(
    +      limitType,
    +      context.rateLimitResetTimes.get(limitType) ?? claudeUsageLimitResetAt(info.resetsAt),
    +    );
    +  }
    • isClaudeBlockedAssistantRateLimit is a Schema.is guard for { api_error_params: { rate_limit_info: { status: "rejected", rateLimitType?, resetsAt? } } }.
    • claudeUsageLimitResetAt is the existing epoch-seconds conversion from the rate_limit_event branch, moved into a helper.

    A wake-harness test in ClaudeAdapterV2.test.ts replays the incident's frames: a limited user turn with a rejected event, then a wake turn with only the blocked assistant frame and a 429 result. It fails on main with expected null to equal '2026-10-06T22:00:00.000Z' and passes with the change. All 144 tests in that file pass, and the server typecheck is clean.

    This may also simplify #15697. Each wake turn's blocked frame names its own reset, so the per-conversation cache and its replay invalidation may not be needed. If maintainers prefer this direction, the test and change are ready to open as a PR.

    mock-api.mjs
    // Minimal stand-in for the Messages API that always answers like an exhausted
    // subscription: HTTP 429 with the unified rate-limit headers the CLI reads.
    // Usage: node mock-api.mjs <port> <resetEpochSeconds>
    import http from "node:http";
    
    const port = Number(process.argv[2] ?? 8787);
    const reset = String(process.argv[3] ?? Math.floor(Date.now() / 1000) + 3600);
    let count = 0;
    
    http
      .createServer((req, res) => {
        let body = "";
        req.on("data", (chunk) => (body += chunk));
        req.on("end", () => {
          count += 1;
          console.log(`${new Date().toISOString()} #${count} ${req.method} ${req.url}`);
          if (req.method !== "POST" || !req.url.startsWith("/v1/messages")) {
            res.writeHead(404, { "content-type": "application/json" });
            res.end(JSON.stringify({ type: "error", error: { type: "not_found_error", message: "mock" } }));
            return;
          }
          res.writeHead(429, {
            "content-type": "application/json",
            "request-id": `req_mock_${count}`,
            "x-should-retry": "false",
            "anthropic-ratelimit-unified-status": "rejected",
            "anthropic-ratelimit-unified-reset": reset,
            "anthropic-ratelimit-unified-representative-claim": "five_hour",
            "anthropic-ratelimit-unified-5h-status": "rejected",
            "anthropic-ratelimit-unified-5h-reset": reset,
            "anthropic-ratelimit-unified-5h-utilization": "1",
            "anthropic-ratelimit-unified-7d-status": "allowed",
            "anthropic-ratelimit-unified-7d-utilization": "0.2",
            "anthropic-ratelimit-unified-overage-status": "rejected",
            "anthropic-ratelimit-unified-overage-disabled-reason": "org_level_disabled",
          });
          res.end(
            JSON.stringify({
              type: "error",
              error: { type: "rate_limit_error", message: "This request would exceed your account's rate limit." },
            }),
          );
        });
      })
      .listen(port, "127.0.0.1", () => console.log(`mock listening on ${port}, reset ${reset}`));
    cli-throttle.mjs (CLI-only check: node cli-throttle.mjs "$(command -v claude)" 18787 1 35)
    // Drives the real CLI headless (stream-json, as the agent SDK does) against
    // mock-api.mjs and reports which limited turns get a rate_limit_event.
    // Usage: node cli-throttle.mjs <claudeBin> <port> <gapsSeconds...>
    // Each gap is the wait before sending the next prompt after the previous result.
    import { spawn } from "node:child_process";
    import { mkdtempSync } from "node:fs";
    import { tmpdir } from "node:os";
    import path from "node:path";
    
    const [bin, port, ...gaps] = process.argv.slice(2);
    const configDir = mkdtempSync(path.join(tmpdir(), "cli-throttle-"));
    const child = spawn(
      bin,
      ["-p", "--output-format", "stream-json", "--input-format", "stream-json", "--verbose"],
      {
        cwd: configDir,
        env: {
          ...process.env,
          CLAUDE_CONFIG_DIR: configDir,
          ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}`,
          // A subscription login is what makes the CLI read unified quota headers.
          // The token is fake and only ever reaches the mock.
          CLAUDE_CODE_OAUTH_TOKEN: "sk-ant-oat01-mock-not-a-real-token",
          ANTHROPIC_API_KEY: "",
          CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
        },
        stdio: ["pipe", "pipe", "inherit"],
      },
    );
    
    const t0 = Date.now();
    const stamp = () => `+${((Date.now() - t0) / 1000).toFixed(1)}s`;
    let turn = 0;
    let sawEvent = false;
    const send = () => {
      turn += 1;
      sawEvent = false;
      console.log(`${stamp()} turn ${turn}: prompt sent`);
      child.stdin.write(
        JSON.stringify({ type: "user", message: { role: "user", content: `ping ${turn}` }, parent_tool_use_id: null }) + "\n",
      );
    };
    
    let buffer = "";
    child.stdout.on("data", (chunk) => {
      buffer += chunk;
      let newline;
      while ((newline = buffer.indexOf("\n")) >= 0) {
        const line = buffer.slice(0, newline);
        buffer = buffer.slice(newline + 1);
        if (!line.trim()) continue;
        const message = JSON.parse(line);
        if (message.type === "rate_limit_event") {
          sawEvent = true;
          const info = message.rate_limit_info;
          console.log(`${stamp()} turn ${turn}: rate_limit_event status=${info.status} resetsAt=${info.resetsAt}`);
        }
        if (message.type === "assistant" && message.error) {
          const info = message.api_error_params?.rate_limit_info;
          console.log(
            `${stamp()} turn ${turn}: assistant error=${message.error} api_error_params.resetsAt=${info?.resetsAt ?? "none"} text=${JSON.stringify(message.message.content[0]?.text)}`,
          );
        }
        if (message.type === "result") {
          console.log(`${stamp()} turn ${turn}: result api_error_status=${message.api_error_status} -> event ${sawEvent ? "SENT" : "MISSING"}`);
          const gap = gaps.shift();
          if (gap === undefined) {
            child.stdin.end();
            return;
          }
          setTimeout(send, Number(gap) * 1000);
        }
      }
    });
    child.on("exit", (code) => console.log(`${stamp()} cli exited ${code}`));
    send();
  7. realhasanshoaib commented on Oct 12, 2026

    @realhasanshoaib
    Contributor

    Confirmed the embedded-only path on today's nightly with Claude Code 2.1.295. Read the retained provider protocol log and V2 projection rows read-only; no live state was changed.

    Two root failures in the same conversation, four seconds apart:

    Frame / persisted field First failure Follow-up failure
    Standalone rate_limit_event five_hour, rejected, resetsAt: 1791804000 Not emitted
    Root assistant api_error_params.rate_limit_info Same rejected window and timestamp Same rejected window and timestamp
    Result api_error_status: 429, terminal_reason: api_error Same
    Persisted failure.resetAt 2026-10-12T11:20:00.000Z null

    That is 3:20 PM in Asia/Dubai, matching Claude's message. Other inspected threads retained the same reset. The follow-up became the latest failure, so recovery controls disappeared and automatic snoozing did not arm for that run.

    Also reproduced through the real web client on unchanged main at 58d253231d, with the real Claude CLI pointed at a local mock subscription limit. A retry 16 seconds after the first failure lost the reset. No automatic continuation was sent after the mock reset passed. No real subscription quota or credentials were used.

    I'm preparing a focused fix that reads the current root assistant's structured payload rather than caching reset times across turns. This follows the reproduction and proposed direction in @EhsanulHaqueSiam's comment above. It preserves event-provided timestamps and the existing recovery settings.

  8. realhasanshoaib commented on Oct 12, 2026

    @realhasanshoaib
    Contributor

    Fix and verification: #18616

    The real CLI follow-up failed 16 seconds after the first limit, without a standalone rate-limit event. With the fix it kept its reset, snoozed, and completed automatically three seconds after reset. Baseline main did not resume. Before is left; after is right. The 32-second browser recording uses a synthetic project and a local mock limit.

    Image
    auto-resume.mp4
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

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions