Repository navigation
[Bug]: Mobile "Resume queue" silently does nothing on a usage-limited thread #27187
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
Mobile app (with server orchestration v2)
Steps to reproduce
- Start a Claude thread and send a message while it is running, so the message is queued.
- Let the running turn fail with a usage limit (a 429 /
usage_limitfailure). - Once capacity is back (limit reset, or another account added), open the thread in the iOS app.
- Tap the composer's Resume queue (play) button.
Expected behavior
The stopped run continues ("Continue where you left off."), then the queued message runs. This is what the web app does.
Actual behavior
Nothing happens on the phone. No error is shown. The server rejects every tap:
OrchestrationV2DispatchCommandError: Continue the limited thread before resuming its queue.
command: queue.resume
Root cause
- The mobile app only sends
queue.resume.handleResumeQueueinapps/mobile/src/features/threads/ThreadRouteScreen.tsx:690callsresumeThreadQueueand nothing else. The button only appears whencomposer.queueHeldis true (line 1080). Mobile never sends a manual continuation:manualContinuationOfRunIddoesn't appear anywhere underapps/mobile. - The server refuses
queue.resumewhile a usage limit is holding the queue. Seeapps/server/src/orchestration-v2/Orchestrator.ts:12715-12727(usageLimitHoldsQueue). It wants the failed run continued first. - The web app already handles this correctly.
ChatView.tsx:817computesresumableRunIdfrom the latest run: either it was interrupted, or it failed andlatestRootProviderFailure(...)reportsclass === "usage_limit". ThenuseComposerResume.ts:105-141sendsstartTurnwithmanualContinuationOfRunIdfirst, and only thenresumeThreadQueue. - The failure is silent.
runAtomCommandreports toconsoleby default (packages/client-runtime/src/state/runtime.ts:340), and the mobilehandleResumeQueueignores the result, so the user gets no feedback.
Without queued messages there's a related gap: mobile has no way to continue a usage-limited or interrupted run at all, except by typing a new message.
Suggested fix
Bring mobile in line with web:
- Move the
resumableRunIdlogic out ofChatView.tsxintoclient-runtime, so web and mobile share it. - In the mobile
handleResumeQueue, whenresumableRunIdisn't null, sendstartTurnwithmanualContinuationOfRunIdfirst, thenresumeThreadQueueif runs are still held. - Show the resume action when
queueHeld || resumableRunId !== null. - Show the command failure in the thread instead of only logging it.
Impact
A thread that hits a usage limit with a queued message can't be continued from mobile at all, and the user isn't told why.
This hits harder when the limit has no reset time. I run Claude through CLIProxyAPI, a local proxy that spreads requests across several Claude accounts. When every account was cooling down, the proxy returned a plain 429 (All credentials for model claude-opus-5-5 are cooling down), so T3 Code couldn't read a reset time. The stored failure is:
{"class":"usage_limit","message":"Claude API rate limit reached. Try again later.","code":"api_error_429","retryable":true,"resetAt":null}With resetAt: null, the automatic resume after the limit resets can never schedule, so a manual continue is the only way out. On mobile that path is missing, so the thread stays stuck even after capacity comes back. Here, capacity came back when I added another account to the proxy.
Version or commit
- Server and runtime: t3 0.1.5 (background service).
- Mobile: iOS app build 202 (user agent
T3Code/202 CFNetwork/3860.700.2 Darwin/25.6.0). - The bug is still present on
mainatdd14848153(2026-10-29).
Environment
macOS host running the t3 background service. iPhone connected through T3 Connect. Claude provider routed through CLIProxyAPI 8.0.40 (ANTHROPIC_BASE_URL set in the Claude provider's environment), so limit responses carry no reset time.
Logs or stack traces
Server trace spans ws.rpc.orchestration.dispatchCommand → Failure, cause Continue the limited thread before resuming its queue., command type queue.resume. They repeat once per tap, each with a new command id.
Workaround
Continue the thread from the web or desktop client, which sends the manual continuation first. Or remove the queued message, send a fresh message, and queue the rest again.
Activity