{"record":{"id":"7372af1ab766aed4","repo":"can1357/oh-my-pi","slug":"ssh-binary-not-found-on-path","errorCode":null,"errorMessage":"ssh binary not found on PATH","messagePattern":"ssh binary not found on PATH","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/ssh/connection-manager.ts","lineNumber":333,"sourceCode":"\t});\n\treturn {\n\t\texitCode: result.exitCode,\n\t\tstdout: result.stdout.trim(),\n\t\tstderr: result.stderr.trim(),\n\t};\n}\n\n/**\n * Test-only surface for exercising the pre-command SSH helpers against a\n * fake `ssh` binary with a shortened timeout. External code MUST NOT depend\n * on this — call `ensureConnection` / `ensureHostInfo` instead.\n * @internal\n */\nexport const _sshHelpersForTests = { runSshSync, runSshCaptureSync };\n\nfunction ensureSshBinary(): void {\n\tif (!$which(\"ssh\")) {\n\t\tthrow new Error(\"ssh binary not found on PATH\");\n\t}\n}\n\nfunction parseOs(value: unknown): SSHHostOs | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim().toLowerCase();\n\tswitch (normalized) {\n\t\tcase \"windows\":\n\t\t\treturn \"windows\";\n\t\tcase \"linux\":\n\t\t\treturn \"linux\";\n\t\tcase \"macos\":\n\t\tcase \"darwin\":\n\t\t\treturn \"macos\";\n\t\tcase \"unknown\":\n\t\t\treturn \"unknown\";\n\t\tdefault:\n\t\t\treturn null;","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/ssh/connection-manager.ts#L315-L351","documentation":"ensureSshBinary checks for the ssh executable on PATH (via $which) before running any SSH operation and throws this error if it is absent. The library shells out to the system ssh (ControlMaster, remote commands), so a native ssh client is a hard requirement.","triggerScenarios":"Any SSH connection/ssh:// operation on a machine without OpenSSH client installed or with a PATH that omits its location.","commonSituations":"Minimal Docker images (no openssh-client), Windows without the optional OpenSSH feature, stripped-down CI runners, running under an environment where PATH was sanitized (GUI-launched apps, cron).","solutions":["Install the client: Debian/Ubuntu `apt-get install -y openssh-client`, macOS `brew install openssh` (or it is preinstalled), Windows: Settings → Optional Features → OpenSSH Client","Verify `which ssh` resolves; fix PATH to include its directory","In Docker, use an image with openssh-client or add it to your Dockerfile","For GUI/cron launches, set PATH explicitly in the launch environment"],"exampleFix":"# before\n$ omp ssh ...   # Error: ssh binary not found on PATH\n# after (Debian/Ubuntu)\n$ sudo apt-get install -y openssh-client\n$ which ssh && omp ssh ...","handlingStrategy":"fallback","validationCode":"import { $which } from \"@oh-my-pi/pi-utils\";\nif (!$which(\"ssh\")) {\n  throw new Error(\"openssh client required: apt install openssh-client / brew install openssh\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await connect(target);\n} catch (err) {\n  if (err instanceof Error && err.message === \"ssh binary not found on PATH\") {\n    console.error(\"Install OpenSSH client and ensure it is on PATH:\", process.env.PATH);\n  }\n  throw err;\n}","preventionTips":["Add openssh-client to Dockerfiles/CI images that use this tool","Check `which ssh` in environment setup scripts","For GUI-launched or cron runs, set PATH explicitly","On Windows enable the optional OpenSSH Client feature"],"tags":["ssh","environment","missing-binary","path"],"backgroundTag":"ssh-binary-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}