Repository navigation
Agent archiving its own thread with t3_thread_organize fails the running turn with "provider event stream closed unexpectedly" #15135
Description
What happened
When an agent calls t3_thread_organize with action: "archive" and no threadId (its own thread) during its turn, the archive succeeds. The run then ends as failed with "The provider event stream closed unexpectedly", even though every earlier step in that turn succeeded. Expected: either the archive waits until the turn ends, or self-archive is refused with a clear error. Reproduces 4 out of 4 runs, desktop app, macOS arm64.
Diagnosis
thread.archive has no active-run guard, and it tears down the caller's live provider session.
t3_thread_organize(apps/server/src/mcp/toolkits/thread/handlers.ts:275) dispatchesthread.archivefor the caller's thread.assertLiveCaller(mcp/threadAccess.ts:40) requires the caller to have an active run, so a self-archive always targets a thread in the middle of a turn.- The decider only rejects threads that are already archived (
orchestration-v2/Orchestrator.ts:2264). Archive cancelsqueuedruns only (:2964) and leaves therunningrun alone. It then detaches every provider session withdetail: "Thread archived."andrevokeMcpCredential: true(:3033-3106). The comment at:3026says this is safe for settle because settle rejects active runs. Archive has no such check. - For a single-thread session (Claude here),
ProviderSessionManager.detachreleases the entry (:1871).releaseEntrythen callsfailSubscribers(:512), which pushesProviderAdapterEventStreamError("Thread archived.")into the run's event stream. RunExecutionService(:1267-1307) still sees the run asrunning, so it writes a failed terminal.ProviderFailure.ts:47maps that to the generic "stream closed unexpectedly" text, and "Thread archived." is never shown.
For comparison: settle rejects active runs (Orchestrator.ts:2352), delete cancels them before detaching (ThreadDeletion.ts:70), and the web UI disables Archive while a thread is running (threadActionMenu.logic.ts:51). That UI code's comment says the server rejects the action, which v2 no longer does. Codex and OpenCode2 sessions take the interruptTurn path in detach, so they would likely end as interrupted instead (not tested). On main (e8545b2), Orchestrator.ts and the MCP toolkit are unchanged since this tag, and releaseEntry still fails subscribers.
Possible fixes: reject thread.archive while a run is active, as settle does, so the agent gets a clear error. Or defer a self-archive until the turn ends.
Steps to reproduce
- In the desktop app, start a thread on Claude.
- Ask the agent to call
t3_thread_organizewithaction: "archive"and nothreadId, then reply "done". - The thread is archived within about 10 ms of the tool call starting, and the run fails with "The provider event stream closed unexpectedly". The tool call item stays
running.
Version
0.0.46-nightly.20261003.2623 (fed41fa)
Environment
macOS 27.0 (26A428) arm64, Node v26.8.2, Claude Code 2.1.288, desktop app with local server
Evidence
# statev2.sqlite projections, 2026-10-03 (UTC). These are the only failed runs in the database.
thread tool started archived_at run failed last tool call
cd17f2c6 09:29:55.154 09:29:55.165 09:29:55.172 t3_thread_organize {"action":"archive"} [running]
feb9e7ee 09:35:33.715 09:35:33.722 09:35:33.729 same
5f2febba 09:55:35.674 09:55:35.683 09:55:35.689 same
3d61eeab 09:55:36.278 09:55:36.289 09:55:36.294 same
94e4b217 09:58:11.197 09:58:11.200 09:58:11.204 same
67d809c6 09:58:17.022 09:58:17.026 09:58:17.029 same
error turn item: {"class":"unknown","message":"The provider event stream closed unexpectedly. Retry the turn; if it keeps failing, check the provider and server logs.","code":null,"retryable":null}Related issues
#14203 (closed) asked for archive to stop the provider session, which v2 now does, but nothing handles a running turn. #14907 (open PR) covers archived threads starting work after setup, which is a different path. I found no existing issue for archiving a thread with a running turn.
Fix applied or workaround
Nothing changed on the machine. Workaround: archive from another thread, or manually after the turn ends. Settle is not a workaround from inside the turn, because it rejects active runs.
Filed by
Claude Code 2.1.288 (claude-opus-5-5) via t3 triage
Activity
juliusmarminge commentedon Oct 3, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks @0pilatos0 for the detailed diagnosis and the database evidence! I confirmed this on current
main(263097a8). The nightly you reported on (fed41fa8) is an ancestor of that commit, and nothing since has changed this path.What happens
thread.archiveonly refuses a thread that's already archived. It cancelsqueuedruns, then detaches every live provider session with detailThread archived.andrevokeMcpCredential: true. A run that ispreparing,starting, orrunningis left in place. By comparison, settle rejects active work before it detaches, and delete cancels active runs first. Archive does neither.The clients already treat archiving a live turn as off-limits.
threadRuntimeCanArchiveallows dropping queued work but not detaching a provider that's preparing, starting, or running, and the web and mobile archive actions are disabled in that state. The menu comment saying the server rejects the action is out of date.A self-archive through
t3_thread_organize(withaction: "archive"and nothreadId) always hits this.readWritableThreadrequires the caller to own an active run, then dispatchesthread.archiveon that same thread. For a single-thread session like Claude, detach releases the session, andfailSubscriberspushes aProviderAdapterEventStreamErrorwith causeThread archived..RunExecutionServicestill sees the run asrunning, so it writes a failed terminal.ProviderFailurethen swaps the cause for the generic "provider event stream closed unexpectedly" text, which matches all six rows you posted. The tool item staysrunningbecause the stream dies before the tool result comes back.Shared multi-thread sessions (Codex, OpenCode) interrupt or unload rather than going through
releaseEntry, so they may end up interrupted instead of failed. That's still untested.Related
#14203 (closed) was about stopping an idle provider process on archive. That teardown is now what kills the live turn. Open PR #14907 is a different path: setup finishing and starting work after the thread is already archived.
Likely fix area
One option is to make
thread.archivereject a thread with a preparing, starting, or running run, the way settle does. The agent would then get a clear error and the turn could finish, while queued work can still be cancelled. Deferring a self-archive until the turn ends would be a new workflow. A maintainer will decide on the fix direction.Your workaround holds: archive the thread only after its turn is idle, either from the UI or from another thread. Archiving it from anywhere while the turn is still running goes through the same server path.
juliusmarminge commentedon Oct 22, 2026
Reproduced on current main 89fe509232, Linux x86_64, with
vp run devin an isolated worktree using copied development state. In the real web client, asked Claude Opus 5.5 to callt3_thread_organizewith{"action":"archive"}and nothreadId, then replydone.Read-only projection evidence (UTC, 2026-10-22):
No matching open issue or PR found in the last 90 days. #22748 has a different trigger (switching providers); #14907 addresses workspace preparation, not an already running turn.
Leaving open for maintainer decision: refusing or deferring an agent's self-archive changes the MCP tool's allowed behavior, which is outside the automated triage fix scope. No implementation or PR created. macOS/Electron was not verified here.
juliusmarminge commentedon Oct 22, 2026
Reproduced on current main defb7e6e6b, Linux x86_64, using an isolated
vp run devserver and the real web client with Claude Opus 5.5. Asked it to callt3_thread_organizewith{"action":"archive"}and nothreadId, then replydone. At 03:16:58.046 UTC the thread archived; at 03:16:58.079 the run failed with “The provider event stream closed unexpectedly.” The tool item remained running. No matching duplicate found in the open issues from the last 90 days. macOS/Electron has not been verified here.