Repository navigation
Closing a terminal tab with a missing persisted session record resurrects the tab — close aborts on tab_not_found before PTY kill and snapshot prune #12920
Description
Summary
A terminal tab in the desync state described in #10747 (present in runtime hot state, no persisted workspace-session record) is not only unclosable from the CLI — it visibly resurrects after every close attempt in the UI. The tab disappears for a moment (optimistic client removal), the close RPC fails with tab_not_found, the runtime republishes the unchanged hot-state snapshot, and the tab reappears. The failure is deterministic, so the tab is immortal until its PTY dies or the runtime restarts.
This report adds two things to #10747:
- The user-facing resurrection loop, with a trace-log timeline of one tab "closed" six times over three hours.
- Evidence that the desync can also arise from a partially completed close (persisted record removed, then a later step failed), not only from a failed reveal at creation time.
Observed behavior
Environment: Linux desktop client, Orca 1.4.x, local runtime plus SSH worktrees.
-
Closing an affected tab in the UI: the tab closes for a moment, then returns within seconds.
-
~/.config/orca/logs/main.trace.ndjsonfor one session (2026-08-06): 14runtime.session-tabs.closespans across three bursts (11:26, 14:18, 14:22) all ended in failure. One tab id appears six times — the user kept re-closing the same resurrected tab. 40 other closes in the same window recordeddecision: allowedand stuck. -
Every failing span carries the same exit:
Error: tab_not_found at OrcaRuntimeService.removePersistedHeadlessTerminalTab (.../out/main/index.js) at OrcaRuntimeService.closeHeadlessMobileTerminalTab (.../out/main/index.js) at OrcaRuntimeService.closeMobileSessionTab (.../out/main/index.js) -
Handle-based
terminal.closeRPCs against the same tabs also fail withtab_not_found, but they kill the daemon PTY session before the handler throws (daemon log showssession-killed/session-exitedin lockstep with the failing RPCs). The terminals then stay gone — close "works" by side effect while reporting an error. This is the only non-restart escape from the loop.
Root cause
Same throw site as #10747, but the ordering inside closeHeadlessMobileTerminalTab is what turns it into a resurrection loop (src/main/runtime/orca-runtime.ts @ f713739, lines ~8049-8108):
removePersistedHeadlessTerminalTab(worktreeId, closedParentTabId, { allowMissing: options.allowMissingPersistedTab })— throwstab_not_foundwhen the persisted row is missing (line ~8057). Only one internal recovery caller passesallowMissingPersistedTab: true.- PTY kill (line ~8084) — never reached.
- Hot-state snapshot prune + republish (line ~8088) — never reached.
So the close aborts with the PTY alive and the hot snapshot untouched. The client already removed the tab optimistically; the next snapshot publication re-adds it.
By the time closeHeadlessMobileTerminalTab runs, closeMobileSessionTab has already resolved the tab from the hot snapshot — the tab provably exists in hot state. A missing persisted row at that point can only mean the persisted and hot states have diverged, and refusing the close can never repair that divergence; it just makes the tab immortal.
How the desync arises
Two origins observed/inferred:
- Never persisted — the failed-reveal path documented in CLI
terminal closecan never close a background tab that failed reveal — headless close path throwstab_not_foundfor tabs that were never persisted #10747. - Partially completed close — a prior close removed the persisted row, then a later step in the same transaction failed (the daemon log shows
session-kill-failedevents), leaving the hot snapshot with a tab whose persisted row is already gone. Every subsequent close then hitstab_not_foundbefore reaching the kill/prune steps.
Suggested fix
Make the headless close idempotent: treat a missing persisted row as "already de-persisted" and continue with the PTY kill and hot-state prune (i.e., what allowMissingPersistedTab: true already does for the relay-recovery caller, applied unconditionally). This fixes both this resurrection loop and #10747's unclosable CLI tabs, and makes the partial-close origin self-healing: the second close attempt completes the interrupted transaction instead of failing forever.
PR to follow.
Activity
AmethystLiang commentedon Aug 6, 2026
thanks for reporting. looking into it
fix: close headless terminal tabs whose persisted session record is m…
waymakerlabs commentedon Aug 12, 2026
I can reproduce a closely related resurrection on macOS (M4 Pro Mac mini, Orca v1.4.180, local runtime).
Reproduction:
orca status --jsonreported a ready/reachable runtime (app PID and runtime ID stayed the same).orca terminal list --jsonshowed 9 terminals.The returned entries were not the same terminal records: they had new
handle,ptyId,tabId, andincarnationIdvalues, while reportingconnected: trueandorphaned: false.Several returned tabs launched Claude with
--resumeusing the same provider session IDs as the pre-close tabs, including:legacy-lens hr 773회 실행 이어가기legacy-lens API 게이트웨이 응답 한도 재현 검증setup-legacy-lens-live-publishingLegacy-lens 계획 1단계 실행A process-tree check also showed fresh chains of:
So this is not only a stale rendered tab: returning to the worktree creates new PTYs/Claude processes and resumes the old provider sessions.
Expected: closing a tab removes it from persisted workspace state and terminates its PTY; returning to the worktree must not restore it.
Actual: the tab disappears after close, but switching worktrees causes Orca to hydrate the old session and create a new terminal tab.
This appears closely related to #12920/#12922, reproduced here on macOS. The
/usr/bin/login -flpqchain may also be related to #13764, but the user-visible failure is persisted tab/session resurrection.waymakerlabs commentedon Aug 12, 2026
Additional observation from the same macOS v1.4.180 reproduction: the result depends on how the tab is closed.
exitin the terminal to terminate the shell/Claude process, the tab appears closed in the current project.--resumefor the same provider session.This suggests that the process-exit/agent-exit path is not recording the same durable close state as the explicit UI-close path. The old provider-session reference remains eligible for restoration, and project/worktree switching then rehydrates it.
Could you check whether the exit path should mark the tab/session as permanently closed (or remove it from persisted workspace state) instead of making it resumable on the next project switch?
tozes commentedon Aug 17, 2026
Fresh reproduction on Linux with Orca 1.4.184. This is still present and now also affects the supervised-worker cleanup path.
At 2026-08-17 12:42 UTC, Orca tried to release two completed worker terminals in the same worktree (
/home/tozes/dev/orca):term_41bcfa18-d16c-4100-ab57-059927f8792b/ PTY...@@04489215term_666f921c-af53-49f7-a999-8bb80769b62e/ PTY...@@12c7a52aFor both terminals,
orca orchestration worker-releasereturned:I followed that recovery exactly.
worker-showproved both Dispatches were completed and both exact PTYs had exited. Replayingworker-releasewith each original request ID returned the sametab_not_foundresult.The daemon log confirms that the close attempts killed both PTYs before the RPC failed:
Afterward,
orca terminal list --worktree <exact-worktree-id> --include-visual-layouts --jsonreturned 0 terminals, while the user-facing terminal/tab remains stubborn and refuses to close. This is a concrete split-brain state: the PTY is gone and the runtime terminal list is empty, but tab cleanup still looks up a missing persisted record and reportstab_not_found.This matches the handle-close variant in the original report: the side effect succeeds, but the close operation still fails because persisted tab removal is not idempotent. It also shows that the issue affects current lifecycle cleanup, not only manual UI close.
PR #12922 already implements the idempotent close behavior and has no CodeRabbit findings. Please approve its pending fork-PR workflow run and review it; this current reproduction blocks reliable worker cleanup and leaves uncloseable terminal UI behind.
nwparker commentedon Aug 23, 2026
Closing as a duplicate of #10747.
Disagree? Please respond! I will re-visit this ticket in 5 days. If you respond, I will re-open it 🙏.
terminal closecan never close a background tab that failed reveal — headless close path throwstab_not_foundfor tabs that were never persisted #10747