{"record":{"id":"43b860a91d4a3c8c","repo":"stablyai/orca","slug":"remote-connection-dropped-click-reconnect-on-the-43b860","errorCode":null,"errorMessage":"Remote connection dropped. Click Reconnect on the SSH target before retrying.","messagePattern":"Remote connection dropped\\. Click Reconnect on the SSH target before retrying\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/filesystem.ts","lineNumber":1182,"sourceCode":"      }\n    ): Promise<GitStatusResult> => {\n      const controller = gitStatusCancellations.begin(event, args.requestToken)\n      const options = {\n        includeIgnored: args.includeIgnored ?? false,\n        ...(args.reuseLineStats === true ? { reuseLineStats: true } : {}),\n        ...(args.branchLineTotalMergeBase === undefined\n          ? {}\n          : { branchLineTotalMergeBase: args.branchLineTotalMergeBase }),\n        ...(args.bypassEffectiveUpstreamNegativeCache === true\n          ? { bypassEffectiveUpstreamNegativeCache: true }\n          : {}),\n        ...(controller ? { signal: controller.signal } : {})\n      }\n      try {\n        if (args.connectionId) {\n          const provider = getSshGitProvider(args.connectionId)\n          if (!provider) {\n            throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)\n          }\n          // Why: await keeps the cancellation token registered until the remote request settles (an early finally would free it).\n          return await provider.getStatus(args.worktreePath, options)\n        }\n        const worktreePath = await resolveRegisteredWorktreePath(args.worktreePath, store)\n        // Why: one registered-worktree lookup feeds both — status polls this\n        // handler, and the scan walks every repo's worktree meta.\n        const repo = getLocalRepoForRegisteredWorktree(store, args.worktreePath, worktreePath)\n        const gitOptions = getLocalGitOptionsForRepo(store, repo)\n        const sharedLinkPaths = repo ? getWorktreeSharedLinkPaths(repo) : []\n        return await getStatus(worktreePath, {\n          ...options,\n          ...gitOptions,\n          ...(sharedLinkPaths.length > 0 ? { sharedLinkPaths } : {})\n        })\n      } finally {\n        gitStatusCancellations.finish(event, args.requestToken, controller)\n      }","sourceCodeStart":1164,"sourceCodeEnd":1200,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/filesystem.ts#L1164-L1200","documentation":"Thrown by the 'git:status' handler (src/main/ipc/filesystem.ts:1182) when args.connectionId is set but getSshGitProvider(connectionId) returns undefined. The SSH git provider map (ssh-git-dispatch.ts) is keyed by connectionId and a provider is removed via unregisterSshGitProvider when the SSH connection drops. The accompanying generation counter increments on each register/unregister so callers can detect a stale connection.","triggerScenarios":"Invoking ipcRenderer.invoke('git:status', { worktreePath, connectionId }) while the SSH connection for that connectionId has disconnected, been torn down, or was never registered. Also after a reconnect that produced a new provider/connectionId while the renderer still holds the stale id.","commonSituations":"SSH TCP session dropped by network sleep/resume; remote relay restarted; rapid branch/target switching racing with teardown; renderer holding a connectionId from before a reconnect.","solutions":["Trigger the app's 'Reconnect' on the SSH target to re-register an SSH git provider.","After reconnect, refresh the connectionId in the renderer (reconnect yields a new id/generation).","Retry the git:status call once the reconnect is confirmed.","If it persists, the SSH target is unreachable: verify network, credentials, and that the relay process is up."],"exampleFix":"// before: invoke status with a stale connectionId\nawait invoke('git:status', { worktreePath, connectionId })\n\n// after: reconnect first, then retry with the fresh id\nif (!await ensureSshConnected(connectionId)) {\n  connectionId = await reconnectSshTarget(targetId)\n}\nawait invoke('git:status', { worktreePath, connectionId })","handlingStrategy":"retry","validationCode":"// Treat a missing provider as a reconnect signal; check connection health first.\nasync function ensureProvider(connectionId: string): Promise<string> {\n  if (await isSshConnected(connectionId)) return connectionId\n  return reconnectSshTarget(connectionId)\n}","typeGuard":null,"tryCatchPattern":"const UNAVAILABLE = /Remote connection dropped|No git provider for connection/\ntry {\n  return await invoke('git:status', { worktreePath, connectionId })\n} catch (e) {\n  if (e instanceof Error && UNAVAILABLE.test(e.message)) {\n    connectionId = await reconnectSshTarget(targetId)\n    return invoke('git:status', { worktreePath, connectionId }) // one retry\n  }\n  throw e\n}","preventionTips":["Drive git calls from the live connectionId held by the SSH session store, not a cached copy.","On reconnect, invalidate cached connectionIds and refresh them.","Back off status polling when the SSH target is known to be down."],"tags":["ssh","git","ipc","network","retry"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}