stablyai/orca · error

SSH_TERMINATE_RECONNECT_REQUIRED

SSH_TERMINATE_RECONNECT_REQUIRED

Error message

${SSH_TERMINATE_RECONNECT_REQUIRED}: SSH relay is not connected; reconnect before terminating remote sessions.

What it means

Thrown during SSH session termination when ownedRelayIds.size > 0 (there are remote PTY leases the user wants to shut down) but the relay provider is unavailable (provider is falsy). The relay provider is the live connection to the SSH relay that actually issues shutdown commands; without it, the terminate request cannot reach the remote shells. The error code SSH_TERMINATE_RECONNECT_REQUIRED is matched by the renderer (ssh-target-remove.ts, ssh-session-termination.ts) to present a 'reconnect first' UX instead of a generic failure.

Source

Thrown at src/main/ipc/ssh.ts:1331

      }
      for (const ptyId of getPtyIdsForConnection(args.targetId)) {
        trackPtyId(ptyId, true)
      }
      for (const lease of leases) {
        if (lease.state === 'terminated') {
          continue
        }
        // Why: 'expired' records that reattach gave up, never that the remote shell died — those are
        // precisely the orphans, so the user's terminate action has to be able to reach them.
        trackPtyId(lease.ptyId, lease.state !== 'expired')
      }
      const ptyIds = Array.from(ptyIdsByRelayId, ([relayPtyId, appPtyId]) => ({
        relayPtyId,
        appPtyId
      }))

      if (ownedRelayIds.size > 0 && !provider) {
        throw new Error(
          `${SSH_TERMINATE_RECONNECT_REQUIRED}: SSH relay is not connected; reconnect before terminating remote sessions.`
        )
      }
      const shutdownResults = provider
        ? await Promise.allSettled(
            ptyIds.map(({ appPtyId }) =>
              provider.shutdown(appPtyId, { immediate: true, keepHistory: false })
            )
          )
        : []
      const shutdownFailures: string[] = []
      for (const [index, result] of shutdownResults.entries()) {
        const { appPtyId, relayPtyId } = ptyIds[index]
        if (result.status !== 'fulfilled' && !isSshPtyNotFoundError(result.reason)) {
          shutdownFailures.push(
            `${relayPtyId}: ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`
          )
          continue

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Reconnect the SSH target to re-establish the relay provider, then retry the terminate action.
  2. If reconnect is not desired and the remote shells are truly orphaned, accept that they will exit on their own keepalive/timeout and dismiss the terminate attempt.
  3. Renderer: detect the SSH_TERMINATE_RECONNECT_REQUIRED code and prompt the user to reconnect, as the dedicated handlers already do.
Defensive patterns

Strategy: try-catch

Validate before calling

const state = await ipcRenderer.invoke('ssh:getState', { targetId })
if (state.status !== 'connected') {
  showNotification('Reconnect before terminating remote sessions.')
  return
}

Try / catch

try {
  await ipcRenderer.invoke('ssh:terminateSessions', { targetId })
} catch (e) {
  if ((e as Error).message.includes(SSH_TERMINATE_RECONNECT_REQUIRED)) {
    promptReconnect(targetId)
  } else throw e
}

Prevention

When it happens

Trigger: User invokes terminate on remote sessions for a targetId whose relay transport dropped (provider undefined) while pty ownership records still exist. The provider may be gone because the connection was severed, the relay reset, or the connectionManager has no live connection object.

Common situations: Network blip disconnected the relay while remote terminals were still alive. A relay reset (ssh:resetRelay) cleared the provider but leases persisted. The user is trying to clean up orphaned sessions discovered after a reconnect.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/b560ce2e3c2a3e48. Report an issue: GitHub.