Skip to content

Direct-SSH snapshot tabs are silently dropped when the worktree catalog resolves their paths late #12902

Closed

Description

@robertnisipeanu

Summary

When a direct-SSH remote workspace snapshot is applied, any snapshot worktree path the local worktree catalog cannot resolve yet is silently dropped and never retried. The tabs under that path — and any sleeping agent sessions bound to them — stay missing until the next full reconnect. To the user this looks like their remote agent session vanishing: activating the worktree shows a brand-new empty terminal instead of the restored session.

Environment

  • Orca 1.4.174 (also reproduced on 1.4.171), macOS (darwin arm64)
  • Direct SSH workspace to a Linux host, claude agent running in a remote worktree tab

What happens

applyDirectSshRemoteWorkspaceSnapshot (src/renderer/src/hooks/remote-workspace-snapshot-apply.ts) imports the pulled snapshot through importRemoteWorkspaceSession with resolveWorktreeId: uniqueWorktreeIdByPath(worktreeIds). In importRemoteWorkspaceSession (src/shared/remote-workspace-session-projection.ts):

for (const [worktreePath, tabs] of Object.entries(remote.tabsByWorktreePath ?? {})) {
  const worktreeId = resolvePath(worktreePath)
  if (!worktreeId) {
    continue          // <-- tabs for this path are dropped, no retry ever happens
  }
  ...
}

The resolver is built from the worktree catalog at apply time. For remote hosts the catalog populates asynchronously — in practice a remote worktree often only resolves after the user activates it in the sidebar. The snapshot apply, however, runs once on connect/reconnect. So the ordering is:

  1. SSH connects, snapshot is pulled and applied. The catalog does not know the remote worktree path yet → its tabs are dropped from the import.
  2. The sleeping-agent wake sweep finds its resume record but logs tab <id> ... not present in any worktree (likely pre-hydration); skipping forever — the tab never appears.
  3. The user clicks the worktree. The catalog now resolves the path, but nothing re-runs the import. The worktree hydrates with no tabs, Orca creates a fresh empty terminal tab.
  4. A subsequent workspace export pushes that tabless state back to the host, so the snapshot itself loses the tabs — the session loss becomes durable.

Reproduction

  1. On a direct-SSH workspace, run an agent (e.g. claude) in a terminal tab of a remote worktree; let the workspace snapshot sync.
  2. Quit Orca. Kill the remote relay daemon on the host (simulates relay restart/update — same thing happens after an app update deploys a new relay).
  3. Relaunch Orca and, before activating anything, let SSH reconnect and the snapshot apply run (catalog is still cold).
  4. Activate the worktree: it comes up with a new empty terminal; the snapshot tabs and the agent resume record never fire.

Expected

Snapshot tabs whose worktree path resolves later should still be hydrated — the import should be retried (bounded) as the catalog fills in, so restored sessions attach to their original tabs instead of being lost.

Fix

PR incoming from this account: it appends a bounded deferred-hydration watcher to applyDirectSshRemoteWorkspaceSnapshot that re-imports late-resolving paths scoped to just those worktrees, additively (never removing live tabs) and without moving user focus. Running patched locally; recovers the exact scenario above.

Related: #12722, #12704, #12751 (adjacent restore/merge issues in the same flow).

Activity

  1. AmethystLiang commented on Aug 6, 2026

    @AmethystLiang
    Contributor

    thanks for reporting. looking into it

  2. nwparker commented on Sep 7, 2026

    @nwparker
    Contributor

    Resolved by merged PR #17948. Snapshot application now reports unplaced worktree paths; target sync waits for catalog placement and pulls a fresh host snapshot when those paths become resolvable. Deferred retries are bounded, preserve conflict/non-authoritative state on failures, and permit converging placement. Reviewed the full issue and comment, and re-ran the deferred-placement-retry and target-sync regression suites successfully. Closing as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions