Skip to content

CLI terminal close can never close a background tab that failed reveal — headless close path throws tab_not_found for tabs that were never persisted #10747

Open

Description

@eisen0419

Summary

A terminal created via CLI that fails reveal at creation time (Terminal reveal timed out ... could not make it discoverable, reported as [background]) becomes permanently unclosable through the CLI:

  • orca terminal list shows the tab normally (tab id, terminal handle, agent status).
  • orca terminal close --terminal <handle> (with or without --tab) consistently fails with {"ok":false,"error":{"code":"runtime_error","message":"tab_not_found"}}.
  • Even after the process inside the PTY exits on its own, the tab entry stays in terminal list indefinitely (until the runtime restarts).

The root cause is an asymmetry: list reads runtime hot state (where the tab exists), while the headless close path requires a persisted workspace-session record (which was never written because reveal/adopt failed). A tab that never made it into the persisted session can therefore never satisfy the close path's de-persist step.

Observed on a relay-connected SSH worktree (relay 0.1.0+0eee5f4c09ed); 6 out of 6 worker terminals created in one session with the [background] warning all reproduced it. Not a transient wedge — retries after the runtime was healthy again failed identically.

Reproduction

  1. orca terminal create --worktree active --command "sh <script>" in a setup where reveal times out (e.g. SSH worktree with the desktop app not foregrounded). Creation output shows Terminal reveal timed out ... could not make it discoverable and the terminal is reported as [background].
  2. orca terminal close --terminal <handle> --tab (or without --tab).
  3. Observe tab_not_found. The tab remains in terminal list.
  4. Optionally let the process inside the PTY exit — the tab entry still remains listed.

Root cause

CLI terminal close → RPC terminal.close / terminal.closeTab (src/cli/handlers/terminal.ts:153-158). Because the renderer never adopted the tab (consistent with the reveal timeout), the close flow classifies it as a runtime-owned headless tab and takes the headless branch:

  • src/main/runtime/orca-runtime.ts:5767-5774 — closingWholeParent && !this.tabs.has(tab.parentTabId) → closeHeadlessMobileTerminalTab(...).
  • src/main/runtime/orca-runtime.ts:5943-5950 — closeHeadlessMobileTerminalTab calls removePersistedHeadlessTerminalTab(worktreeId, parentTabId).
  • src/main/runtime/orca-runtime.ts:5206-5220 — removePersistedHeadlessTerminalTab runs closeTerminalTabInWorkspaceSession(session, worktreeId, parentTabId) against the persisted session (src/shared/workspace-session-terminal-tab-close.ts). The tab was never persisted, so result.closed is false → throw new Error('tab_not_found').

So the failure is not "tab does not exist" — the tab exists in hot state and is listed — but "tab has no persisted record to remove". Two secondary effects compound it:

  • PTY exit terminates the PTY but does not reap the hot-state tab entry, so dead [background] tabs accumulate in terminal list until the next runtime restart rebuilds hot state from the persisted session.
  • There is no CLI-reachable fallback: every close variant funnels into the same de-persist step.

Suggested direction

When the headless close path finds no persisted record for a tab that does exist in runtime hot state, it should degrade instead of throwing: kill the PTYs it knows about, drop the hot-state tab entry, and report success — the invariant "persisted record exists" simply does not hold for never-adopted background tabs. Alternatively (or additionally), reap hot-state tab entries when their last PTY exits, and/or persist the tab even when reveal times out so the normal close transaction applies.

Happy to provide the full CLI transcripts from the 6-terminal reproduction if useful.

Activity

  1. AmethystLiang commented on Jul 26, 2026

    @AmethystLiang
    Contributor

    thanks for reporting this. will look into it!

  2. nwparker commented on Jul 27, 2026

    @nwparker
    Contributor

    Repro status: has_repro (code-path, conclusive)

    Summary

    CLI terminal close cannot close a background tab that failed reveal: list shows the tab (hot state), close throws tab_not_found because the headless close path requires a persisted workspace-session record that was never written.

    Code evidence

    1. List reads runtime hot state (tab exists after background create with reveal timeout).
    2. Headless close → closeHeadlessMobileTerminalTab → removePersistedHeadlessTerminalTab (src/main/runtime/orca-runtime.ts ~5490, ~6246).
    3. removePersistedHeadlessTerminalTab de-persists via workspace session; if no record, throws tab_not_found (~5500).

    Repro steps

    1. Create terminal where reveal times out → [background] / "Terminal reveal timed out … could not make it discoverable".
    2. orca terminal list — tab present.
    3. orca terminal close --terminal <handle> → tab_not_found.
    4. Tab remains listed until runtime restart.

    Expected

    If tab exists in hot state but has no persisted record, kill PTYs, drop hot entry, succeed (or persist even when reveal fails).

  3. added
    has_reproConclusive reproduction exists (test/script/CLI evidence). See docs/bug-reproductions/
    on Jul 27, 2026
  4. danielxxomg commented on Aug 4, 2026

    @danielxxomg

    Additional reproduction on a remote folder workspace (client 1.4.163, headless runtime 1.4.164, Linux client).

    I hit the same hot-state/persisted-state mismatch while cleaning up a remote folder workspace.

    Environment

    • Linux desktop client, Orca 1.4.163 (orca-ide)
    • Saved remote headless Orca runtime, 1.4.164
    • The remote runtime reported ready while its desktop app was not running.
    • The UI showed three workspace entries. The remote CLI was initially queried without the environment selector and incorrectly returned zero. With the saved remote environment selected, terminal list --json reported three connected/writable terminals: one floating root terminal and two terminals in one folder-backed headless group.

    Observed cleanup

    1. terminal close --tab succeeded for the floating root terminal, but reported ptyKilled: false.
    2. After re-listing, both folder terminals were still present with connected: true and writable: true.
    3. Closing a listed folder terminal with --tab returned tab_not_found; the pane-close variant returned terminal_handle_stale.
    4. terminal show still returned the terminal, and terminal list continued to report it after the failed close attempts.
    5. terminal stop --worktree ... returned selector_not_found; worktree ps and project setups were empty for the remote runtime, even though terminal list exposed a folder workspace ID.

    Expected behavior

    A terminal returned by terminal list should be closable using its current identity. Once the last terminal in a folder workspace is closed, the folder workspace should disappear from the client, or the CLI should expose a stable folder selector for cleanup.

    Actual behavior

    The list/show paths and close paths disagree for the remote folder terminals. The terminals remain visible and connected after the close failure, and there is no CLI cleanup path through the worktree selector. No filesystem deletion was attempted.

    Minimal reproduction

    1. Pair a desktop client with a headless remote Orca runtime.
    2. Open a folder workspace and create two terminal tabs.
    3. Query terminal list --environment <saved-environment> --json.
    4. Run terminal close --environment <saved-environment> --terminal <listed-handle> --tab and retry without --tab.
    5. Observe tab_not_found / terminal_handle_stale, then re-run terminal list and terminal show.

    This appears related to #10747's hot-state versus persisted-session mismatch and #11875's terminal-handle/close-path disagreement. The additional aspect here is that the affected terminals belong to a folder-backed remote headless workspace that does not resolve as a worktree selector.

  5. added a commit that references this issue on Aug 10, 2026
    e29b0be
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinghas_reproConclusive reproduction exists (test/script/CLI evidence). See docs/bug-reproductions/

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions