{"record":{"id":"d0ed1192fb3869dc","repo":"stablyai/orca","slug":"failed-to-terminate-ssh-host-sessions-shutdownf","errorCode":null,"errorMessage":"Failed to terminate SSH host sessions: ${shutdownFailures.join('; ')}","messagePattern":"Failed to terminate SSH host sessions: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/ipc/ssh.ts","lineNumber":1357,"sourceCode":"            )\n          )\n        : []\n      const shutdownFailures: string[] = []\n      for (const [index, result] of shutdownResults.entries()) {\n        const { appPtyId, relayPtyId } = ptyIds[index]\n        if (result.status !== 'fulfilled' && !isSshPtyNotFoundError(result.reason)) {\n          shutdownFailures.push(\n            `${relayPtyId}: ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`\n          )\n          continue\n        }\n        clearProviderPtyState(appPtyId)\n        deletePtyOwnership(appPtyId)\n        persistedStore!.markSshRemotePtyLease(args.targetId, relayPtyId, 'terminated')\n      }\n      if (shutdownFailures.length > 0) {\n        // Why: a failed relay shutdown can leave the remote process alive in the grace window; keep the lease/session so the user can retry.\n        throw new Error(`Failed to terminate SSH host sessions: ${shutdownFailures.join('; ')}`)\n      }\n      await teardownSshTargetTransport(args.targetId, (session) => session.disposeAndPersist())\n    })\n  })\n\n  async function doResetRelay(targetId: string, target: SshTarget): Promise<void> {\n    const inFlightConnect = connectInFlight.get(targetId)\n    if (inFlightConnect) {\n      try {\n        // Why: resetting activeSessions mid-deploy would dispose the session doConnect will use.\n        await inFlightConnect.promise\n      } catch {\n        // The reset can still recover a stale remote relay after a failed connect.\n      }\n    }\n\n    rotateSshProviderAuthority(targetId)\n    const session = activeSessions.get(targetId)","sourceCodeStart":1339,"sourceCodeEnd":1375,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/ssh.ts#L1339-L1375","documentation":"Thrown after attempting to shut down remote SSH PTY sessions when one or more provider.shutdown() calls rejected with a reason that is not an 'SSH pty not found' error. Non-not-found failures indicate the remote shell may still be alive in the grace window, so the code intentionally keeps the lease/session intact to let the user retry. The aggregated relayPtyId:reason pairs are joined so the caller can see which specific sessions failed and why.","triggerScenarios":"Promise.allSettled over ptyIds where at least one provider.shutdown(immediate:true, keepHistory:false) rejected with a transport error, timeout, permission error, or unexpected relay response. isSshPtyNotFoundError filtered out only the benign already-gone case.","commonSituations":"Relay under load returns a transient error. Remote shell is wedged and ignores the shutdown signal within the timeout. Permission/quota issue on the remote host blocks process termination. Partial network partition where some shutdowns succeed and others fail.","solutions":["Retry the terminate request; transient relay errors often clear on the second attempt.","Inspect the per-pty reasons in the message to identify which remote host/session is stuck, then address that shell directly (e.g. log in and kill the PID).","If the relay itself is unhealthy, run 'ssh:resetRelay' first to rebuild the transport, then retry terminate.","As a last resort for truly wedged remote shells, accept the lease stays and let the remote OS reap the process."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 2; attempt++) {\n  try {\n    await ipcRenderer.invoke('ssh:terminateSessions', { targetId })\n    break\n  } catch (e) {\n    if (attempt < 1 && /Failed to terminate SSH host sessions/.test((e as Error).message)) continue\n    showTerminationFailures((e as Error).message)\n    throw e\n  }\n}","preventionTips":["Retry once after a brief delay — transient relay shutdown failures often clear.","Parse the per-pty failure list from the message to target stuck remote shells.","Consider ssh:resetRelay if repeated terminate attempts fail with transport errors."],"tags":["ssh","relay","session-termination","partial-failure","retry"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}