Skip to content

fix(mobile): queue sheet's Resume queue continues a usage-limited thread - #35576

Merged
juliusmarminge merged 3 commits into
mainfrom
factory/issue-35554
Nov 12, 2026
Merged

juliusmarminge merged 3 commits into
mainfrom
factory/issue-35554

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

Review item 1 was correct. The server's queue.resume guard (usageLimitHoldsQueue) checks the next queued message's provider, which the client cannot reliably predict, so any client-side decision to continue first can insert an unwanted turn on the limited provider. Rather than add more machinery, this pass removes the client-side continuation entirely. The sheet's Resume queue sends queue.resume exactly as main does, now with reportFailure: false, and on a non-interrupt failure shows a 'Could not resume queue' dialog with the server's message. For the reported case that message is 'Continue the limited thread before resuming its queue.', which points the user to the composer's Resume thread. The issue's expected behaviour explicitly allows this. Traced by reading the code, not observed: ws.ts maps dispatch failures through userFacingDispatchErrorMessage, which picks up the guard's text, so the dialog should show it. Compared with the branch base the only change is ThreadQueueControl.tsx, adding the dialog. The earlier resumeThread wiring, deriveResumableRunId selector and extra commands are all gone. Not exercised on a device.

Fixes #35554

Reproduction on main

Commit 77f40af (origin/main). Fresh dev database (T3CODE_DEV_SEED=0, vp run dev with T3CODE_LAN=1). The real Claude provider (claude-haiku-4-5) was pointed via ANTHROPIC_BASE_URL and a private CLAUDE_CONFIG_DIR at a local stub that waits 20 s, then answers POST /v1/messages with 429 rate_limit_error and x-should-retry: false. Steps: t3 project add a scratch git repo; t3 thread start --provider claudeAgent --model claude-haiku-4-5 with "Start"; while it ran, t3 thread send "Follow up" (reported Queued). The run failed; the persisted error item has failure {class: usage_limit, code: api_error_429, resetAt: null}. The queued run was not held yet. Restarted the dev server, and startup recovery set queueHeld=true on the queued run. Android Pixel 9 from the device pool, T3 Code Dev client installed with vp run mobile:install android --session, paired to the dev server. The thread shows the 'Usage limit reached. The provider did not report a reset time.' banner and '1 queued'. Tapped '1 queued': the sheet shows 'Queue paused', an enabled 'Resume queue' button and the 'Follow up' row with Send now. Tapped Resume queue: the sheet is unchanged, with no dialog or inline message. The database still has the failed run and the queued run with queueHeld=true. The only trace is a Metro console line WARN [atom-command] resume queue failed. The composer's 'Resume thread' button was present as the working recovery.

Evidence

Reproduced on Android Pixel 9 with fresh databases: start a turn, queue Follow up, receive a delayed 429 usage limit, restart for queue recovery, then open 1 queued and tap Resume queue. Base silently refuses; head displays the refusal and directs the user to continue the limited thread.

Before After
1001bc71fc b15509a3e7
Before: queue remains paused without feedback After: refusal dialog explains the required action
Before recording After recording

Reproduction driver · Delayed rate-limit stub

AI-assisted; verified with the tests and tools listed above.

Tests

vp run check:changed: format, lint, knip, typecheck (2 packages), react compiler all passed.

Not in this change

  • A row's 'Send now' on a held queue sends queue.resume with a runId. The same usage-limit guard refuses it, and that failure is still only logged.
  • The sheet continues with the thread's saved interaction mode and model, while the composer's Resume thread forces build mode and uses the composer's selected model. The difference only shows on plan-mode threads or when the composer has a different model selected.
  • The composer's Resume thread still continues interrupted runs before resuming the queue. That is its existing behaviour from fix(mobile): resume continues a usage-limited thread before its queue #27662 and was left unchanged.
  • The sheet does not offer an in-place way to continue a usage-limited run. The dialog points to the composer's Resume thread instead.

AI-assisted; verified with the tests and tools listed above.

The queue sheet sent a bare queue.resume, which the server refuses while a
usage-limited run awaits manual continuation, and dropped the refusal.
Route the button through resumeThread, as the composer's Resume thread does,
and show any failure in a dialog.

AI-assisted; verified with the tests and tools listed above.
…suming

A stopped run does not hold queue.resume, so Resume queue after Stop runs
the queued messages without first continuing the stopped work.

AI-assisted; verified with the tests and tools listed above.
The queue.resume guard depends on the next queued message's provider, which
the client cannot reliably predict, so the sheet no longer starts a
continuation itself. It sends queue.resume as before and shows the server's
refusal, which names the action that works.

AI-assisted; verified with the tests and tools listed above.
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Nov 12, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at b15509a

Macroscope's review found this PR approvable — The mobile queue sheet now shows an alert when Resume queue fails, while ignoring interrupted commands. Queue execution and usage-limit behavior remain unchanged; the change is limited to failure reporting.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The mobile queue sheet now handles failures from the held-queue resume command. It clears the busy state and shows an alert for failures other than interrupted commands.

Changes: Held queue resume

Layer / File(s) Summary
Resume command and failure alert
apps/mobile/src/features/threads/ThreadQueueControl.tsx
The held-queue resume action uses a separate command with automatic failure reporting disabled. After the command completes, the sheet clears its busy state and alerts for non-interrupted failures. The alert uses the squashed error message when available, or “Try again.”

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Possibly related PRs

  • pingdotgg/t3code#27190: Addresses the same mobile Resume behavior for usage-limited threads, but uses a different approach.

Suggested reviewers: t3dotgg, etanhey, maria-rcks

Merge Risk: Minimal · up to b1550

The change makes the mobile queue sheet explain why Resume queue was refused instead of failing silently. No concrete merge-blocking risk was identified.

Pre-merge checks: Passed 3 · Inconclusive 1

Failed Failed checks: 1 inconclusive

Check name Status Explanation Resolution
Linked Issues check Inconclusive [#35554] The reviewed diff changes only apps/mobile/src/features/threads/ThreadQueueControl.tsx. The Resume queue action now sends queue.resume through a command with reportFailure: false. On a non-in… Confirm, from the server source or a device run, the exact text returned when queue.resume is refused for a usage-limited thread. If that text does not direct the user to Resume thread, change the server message or the dialog text so it nam…
Passed Passed checks: 3 passed

Check name Status Explanation
Title check Passed The title names the main change: the mobile queue sheet's Resume queue action no longer continues a usage-limited thread. The raw summary confirms the resume flow now shows a failure alert and does no…
Out of Scope Changes check Passed The whole-PR diff against the merge base contains one file, ThreadQueueControl.tsx. Its additions serve the Resume queue objective. They add the Dialog import, the atom-command helpers isAtomCommandIn…
Description check Passed The description covers the problem (the sheet's Resume queue sends queue.resume and the usage-limit guard refuses it silently), the change (client-side continuation removed, a 'Could not resume queue'…
Full details: Title check

Explanation

The title names the main change: the mobile queue sheet's Resume queue action no longer continues a usage-limited thread. The raw summary confirms the resume flow now shows a failure alert and does not continue the run, so the title's wording ('continues a usage-limited thread') describes the prior bug rather than the new behavior. It is specific and scoped to mobile, but its verb points at the old behavior. The title is still related to the changeset, so it passes with a note.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff against the merge base contains one file, ThreadQueueControl.tsx. Its additions serve the Resume queue objective. They add the Dialog import, the atom-command helpers isAtomCommandInterrupted and squashAtomCommandFailure, a separate resumeHeldQueue command with reportFailure: false, and the failure alert after the busy state is cleared. The existing resume command remains in use for other queue actions. No unrelated files or behavior changes appear in the diff. The PR description says the earlier resumeThread wiring, deriveResumableRunId selector, and extra commands were removed, and the diff agrees.

Full details: Description check

Explanation

The description covers the problem (the sheet's Resume queue sends queue.resume and the usage-limit guard refuses it silently), the change (client-side continuation removed, a 'Could not resume queue' dialog shows the server message), scope (links issue #35554 and explains the fix is a bug fix), verification (reproduction on Android Pixel 9 with before/after evidence, check:changed results, and a note that the trace-only part was not exercised on device), and the agent/model attribution note. The template's Verification section is satisfied, with clear before/after screenshots and recordings. Minor gap: the 'AI-assisted' line does not name the model and harness as the template asks, and the description repeats the AI-assisted line twice.

Full details: Linked Issues check

Explanation

[#35554] The reviewed diff changes only apps/mobile/src/features/threads/ThreadQueueControl.tsx. The Resume queue action now sends queue.resume through a command with reportFailure: false. On a non-interrupt failure, it shows a 'Could not resume queue' alert with the squashed server error, or 'Try again.' This meets the issue's 'explains the refusal' path. The issue also requires that the explanation direct the user to Resume thread. The direction depends on the server's refusal text, which the PR quotes as 'Continue the limited thread before resuming its queue.' That text does not name the composer's Resume thread control. The server guard source is outside the reviewed diff and was not inspected, so the displayed text is unverified. The PR states that the behavior was traced by reading code, not observed on a device. The provider_error path is unchanged because it still sends the same queue.resume request. The composer Resume thread path is unchanged. Send now on a held queue is not changed and is listed as out of scope by the PR.

Resolution

Confirm, from the server source or a device run, the exact text returned when queue.resume is refused for a usage-limited thread. If that text does not direct the user to Resume thread, change the server message or the dialog text so it names the composer's Resume thread action. Record the observed dialog text in the Evidence section.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between abca547 and b15509a.

Files selected for processing: 1

  • apps/mobile/src/features/threads/ThreadQueueControl.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

@juliusmarminge
juliusmarminge merged commit 49b0cc3 into main Nov 12, 2026
34 checks passed
@juliusmarminge
juliusmarminge deleted the factory/issue-35554 branch November 12, 2026 20:17
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Nov 12, 2026
**v0.1.10-nightly.20261112.4606** · 4 changes from 3 contributors

**3 bug fixes.**

<details>
<summary>Full changelog</summary>

## What's Changed
* fix(web): the Fix action on a thread details PR row stays inside the card by @pouyarezvani in pingdotgg/t3code#31115
* fix(mobile): queue sheet's Resume queue continues a usage-limited thread by @juliusmarminge in pingdotgg/t3code#35576
* fix(server): background status fetch no longer breaks a concurrent git pull by @juliusmarminge in pingdotgg/t3code#26568
* test(web): Mermaid rejection test waits for the viewer chunk to load by @t3dotgg in pingdotgg/t3code#35586


**Full Changelog**: pingdotgg/t3code@v0.1.10-nightly.20261112.4603...v0.1.10-nightly.20261112.4606

</details>


Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.10-nightly.20261112.4606
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Mobile queue sheet silently refuses Resume queue on a usage-limited thread

1 participant