Skip to content

Two remaining single-snapshot absence inferences in remote-runtime-pty-transport (siblings of #20917 / #17825) #20923

Closed

Description

@YgorLeal

Found while fixing #20917 (PR #20922); out of scope there because neither produces that report's symptom.

Both are the same class the fix in #20922 closes on the attach path: a client-side inventory snapshot missing a surface is treated as host removal evidence, from a single observation, off listRemoteRuntimeSessionTabsDeduped — which joins whatever session.tabs.list is already in flight for the worktree and can therefore answer with a snapshot taken before the pane's own leaf was published.

Per docs/reference/ssh-execution-boundary.md that collapses unverifiable into exited. The stricter convention is already established in web-session-terminal-orphan-recovery-inventory.ts: an explicit retiredTerminalSurfaces proof, or two authoritative inventories omitting the identity.


1. waitForResubscribeHostSessionHandle retires on one listing, with no sibling gate

src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts:862-865

if (request === 'list') {
  if (!hasHostSessionTerminalSurface(listed, hostTabId)) {
    return { handle: null, inventoryFailed: false }
  }

hasHostSessionTerminalSurface matches the requested leaf, so this returns null — which the caller turns into retireRemoteTerminalId(-1) at :1802-1807 — both when the tab publishes siblings but not this leaf and when the snapshot carries no surface for the tab at all.

That second case is exactly what #17945 declared insufficient on the attach path, where the same shape now keeps polling inside the bounded window:

a populated surface list missing only this leaf is positive absence, but a list carrying no surface at all for the tab is a client-side snapshot of a host that may still be republishing

The resubscribe twin never got that treatment, and it has no sibling gate at all — so it is strictly weaker than the branch #20922 has just tightened. It also reads the deduped listing (:835), so it inherits the shared-snapshot hazard: a reconnecting pane can retire on an inventory another pane started before the host republished the surface.

Less damaging than finding 2 — retireRemoteTerminalId is a quiet retirement that leaves the tab recoverable from a later snapshot, per its own comment — but it does fire onPtyExit(stalePtyId, -1) and latch terminalEnded, so the pane reports an exit its host never attested.

2. attach() latches the pane in connecting with no banner and no retry

src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts:2515-2518

if (!resolved) {
  surfaceErrorMessage('Remote terminal was closed.')
  return
}

resolvePersistedHostPane() returns null for a terminal_not_found from terminal.resolvePane, and the host raises that name for two different situations (orca-runtime-resolve-terminal-pane.ts:19-41): no handle currently bound to the pane key, and a worktree-ownership mismatch. Neither is process-liveness evidence.

The branch is also missing the state handling its sibling in attachHostSessionMirror performs before surfacing the same string (:976-981):

connecting = false
emitRecoveryState()
surfaceErrorMessage('Remote terminal was closed.')

attach() sets connecting = true on entry and cancels recovery, and this path clears neither. getRecoveryState() (:460-481) therefore keeps reporting phase connecting — the state #17945's own commit message describes as the dead end:

a silent 'connecting' renders no banner and retryRecovery() refuses to run

So the pane shows an undismissable "Remote terminal was closed." with no Reconnect affordance and no parked retry, which is the shape of #9194 and #15141.


Refs #20917, #20922, #17825, #17945, #9194, #15141.

Activity

  1. AmethystLiang commented on Sep 16, 2026

    @AmethystLiang
    Contributor

    thanks for reporting. looking into it

  2. LesleyMurfin commented on Sep 17, 2026

    @LesleyMurfin
    Contributor

    Cross-referencing: Linking PR #21277 and PR #20922 as part of the broader remote tab lifecycle and transport hardening cluster. While #20923 addresses single-snapshot absence inferences in the remote PTY transport layer, PR #21277 hardens the host RPC and client lifecycle against absent selectors and missing tabs to eliminate ghost tab resurrection loops.

  3. added
    bugSomething isn't working
    orca-remote-serverRemote Orca Server / orca serve / paired remote runtime
    on Sep 19, 2026
  4. added theissue type on Sep 19, 2026
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 workingorca-remote-serverRemote Orca Server / orca serve / paired remote runtime

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions