Skip to content

Auto-settle on PR merge settles a usage-limited thread, so "Resume at reset" and "Snooze until reset" always fail #28362

Description

@EhsanulHaqueSiam

What happened

A thread whose PR had merged hit a provider usage limit. In the same second the run failed, the auto-settle sweep settled the thread. The usage-limit banner still offered "Resume at reset" and "Snooze until reset", but every press failed with "The provider limit changed before recovery could be configured." The limit had not changed.

Diagnosis

Three defects combine:

  1. isAutoSettlementCandidate (ThreadSettlementService.ts) does not skip a thread whose latest run failed with usage_limit. The failure ends the run that kept the thread active, and pullRequestSettles passes because the PR merged after the last user-authored message. A usage limit interrupts work; settling there defeats limit recovery, since settled threads are deliberately excluded from it (recovery guard, UsageLimitRecoveryWorker, storage cleanup hold).
  2. The web banner (ChatView limitRecoveryBanner) and mobile UsageLimitRecoveryCard show the recovery actions on a settled thread, which the server always refuses.
  3. The limitRecovery guard in Orchestrator.ts reports the settled case with the shared "provider limit changed" message, which names the wrong cause.

Why settle-on-merge fired: runs 2 to 4 came from PR-watch and system wakes, so the latest user-authored message predated the merge although the thread was still working through a multi-PR task.

Steps to reproduce

  1. Leave settle-on-merge at its default.
  2. A thread opens a PR that merges, then keeps working on PR-watch or system wake runs with no new user message.
  3. A later run fails with a provider 429 that carries a reset time.
  4. The thread shows "Settled" beside the usage-limit banner.
  5. Press "Resume at reset" or "Snooze until reset". It fails with "The provider limit changed before recovery could be configured."

Version

0.1.7-nightly.20261031.3991 (server, commit 15fe283)

Environment

macOS arm64 (Darwin 27), background server; client T3 Code Desktop 0.1.7-nightly.20261031.3991 on Linux; claudeAgent via a custom inference gateway

Evidence

server.trace.ndjson, UTC:

  • 20:46:13 run 4 fails, error item failure.class: usage_limit, resetAt 21:10:17
  • 20:46:13 ThreadSettlementServiceV2.sweep dispatches thread.auto-settle (Success); the user sent no thread.settle
  • 20:49:15, 20:49:17, 20:51:17, 20:51:51 four thread.metadata.update with limitRecovery fail: "The provider limit changed before recovery could be configured."
  • 21:10:15 a user message un-settles the thread and run 5 starts

Reproduced on main with scripts/seed-issue-21397.py: settle the limited fixture thread, press Resume at reset, same error.

main: settled usage-limited thread still offers Resume at reset; pressing it fails with "The provider limit changed before recovery could be configured."

Related issues

#17808, #14169, #24232. Fix PRs: #28359 (auto-settle), #28360 (banner and message)

Fix applied or workaround

Un-settle the thread first, then press Resume at reset, or send a message. Turning off settle-on-merge avoids it.

Activity

  1. camescasse commented on Nov 2, 2026

    @camescasse

    Additional confirmation from another user on stable T3 Code 0.1.6, with persisted events establishing that the server automatically settled an unfinished, usage-limited thread.

    Environment

    • Linux x64, kernel 7.2.11-arch1-1; T3 Code Desktop connected to its local server, both 0.1.6 (commit 2359643cffa6ba9ee84d6f2694b935de54a8013e).
    • Node v26.12.1; Claude Code 2.1.316; claudeAgent / claude-opus-5-5 through a custom API endpoint.
    • autoResumeLimitedThreads: true. Settle-on-merge was not overridden in the settings file, so the release default, sidebarAutoSettleOnMerge: true, applies.

    Observed sequence, 2026-11-02, UTC

    15:59:14.110  Parent run 95 becomes failed (usage_limit).
    16:00:15.103  thread.settled, command ID begins server:auto-settle:.
    16:00:15.124  A delegated-completion dispatch reopens the parent.
    16:00:16.172  Parent run 96 becomes failed (usage_limit).
    16:00:16.222  thread.settled, command ID begins server:auto-settle:.
    16:06:59.200  User explicitly reopens the thread.
    

    The second settlement happened 50 ms after the usage-limit failure. Server traces independently show successful thread.auto-settle dispatches at both settlement times. The settlement event also detached the provider session with reason Thread settled.

    All four linked PR snapshots were merged; their merge times were 07:29, 07:37, 13:05, and 14:53 UTC that day. The parent was still handling ongoing work and delegated completions when the rate limit occurred.

    In the matching release, isAutoSettlementCandidate does not exclude usage-limit failures. Once running work ends, the merged-PR settlement path can settle the thread.

    This case confirms the automatic-settlement defect. Unlike the original report, these failures had resetAt: null, so recovery-button rejection was not reproduced: the banner instead said Reset time unavailable; retry manually. The missing-reset path is also reported in #26574. Settled threads are independently excluded from recovery.

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