{"record":{"id":"e6691cafeaa9b935","repo":"can1357/oh-my-pi","slug":"ssh-target-name-is-a-windows-host-ssh-s","errorCode":null,"errorMessage":"ssh://: ${target.name} is a Windows host; ssh:// supports POSIX remotes only (head/cat/mv) — use `bash` with a remote SSH command for Windows hosts","messagePattern":"ssh://: (.+?) is a Windows host; ssh:// supports POSIX remotes only \\(head/cat/mv\\) — use `bash` with a remote SSH command for Windows hosts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/ssh/file-transfer.ts","lineNumber":32,"sourceCode":"const DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Ensure the ControlMaster connection and pick the verified POSIX shell to\n * run transfer commands under. Returns the shell name so the caller can\n * wrap its snippet in `<shell> -c '…'`; OpenSSH otherwise hands the command\n * to the user's login shell, which on fish/csh/tcsh hosts can't parse our\n * `if [ … ]; then …` constructs (#3719).\n *\n * Windows hosts are refused up front — `ssh://` runs `head`/`cat`/`mv`/`test`\n * directly and cmd/powershell can't drive those. Everywhere else, we require\n * a non-empty `transferShell` (set by `probeHostInfo` after `sh -lc` /\n * `bash -lc` / `zsh -lc` round-trips a marker against the remote).\n */\nasync function ensurePosixRemote(target: SSHConnectionTarget): Promise<\"sh\" | \"bash\" | \"zsh\"> {\n\tawait ensureConnection(target);\n\tconst info = await ensureHostInfo(target);\n\tif (info.os === \"windows\") {\n\t\tthrow new Error(\n\t\t\t`ssh://: ${target.name} is a Windows host; ssh:// supports POSIX remotes only (head/cat/mv) — use \\`bash\\` with a remote SSH command for Windows hosts`,\n\t\t);\n\t}\n\tif (!info.transferShell) {\n\t\tthrow new Error(\n\t\t\t`ssh://: ${target.name} has no verified POSIX shell for ssh:// read/write — none of sh/bash/zsh round-tripped a capability probe (use \\`bash\\` with a remote SSH command for this host)`,\n\t\t);\n\t}\n\treturn info.transferShell;\n}\n\nexport interface RemoteFileReadOptions {\n\t/** Maximum bytes to materialize; the helper fetches one extra byte to detect truncation. */\n\tmaxBytes: number;\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n}\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/ssh/file-transfer.ts#L14-L50","documentation":"The ssh:// file-transfer path (head/cat/mv style operations) only works against POSIX remotes. ensurePosixRemote consults the cached/probed host info and throws this error when the remote is detected as Windows, directing you to use the bash tool with a remote SSH command instead.","triggerScenarios":"Performing ssh:// read/write (upload/download/head/cat/mv/write) against a target whose probed host OS is \"windows\" — e.g. Windows OpenSSH server where `bash -lc`/`zsh -lc` marker round-trip fails but cmd/powershell responds.","commonSituations":"Pointing ssh:// tools at a Windows Server with OpenSSH installed, mixed fleet where one host is Windows, mis-probed OS due to a POSIX shell shim on Windows (rare).","solutions":["Use the bash tool with an explicit remote SSH command (e.g. `ssh host type file`) for Windows hosts","Install/use a POSIX environment on the remote (WSL, Git Bash, Cygwin) and target that properly if you need ssh:// semantics","Verify the host OS probe result is correct; if the host is actually POSIX, re-probe/fix host info"],"exampleFix":"// before: ssh:// read on a Windows host\nawait readRemoteFile(winTarget, \"C:/logs/app.log\");\n// after: run a remote command instead\nawait runSsh(winTarget, [\"type\", \"C:\\\\logs\\\\app.log\"]); // via bash tool remote command","handlingStrategy":"validation","validationCode":"import * as fs from \"node:fs/promises\";\n// detect Windows remotes up front via a cheap probe command\nconst probe = await $`ssh ${targetArg} ver`.quiet().nothrow();\nif (probe.exitCode === 0 && /Microsoft Windows/i.test(probe.stderr.toString() + probe.stdout.toString())) {\n  throw new Error(\"remote is Windows: use bash tool with remote ssh command, not ssh://\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await readRemoteFile(target, path);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"is a Windows host\")) {\n    // route this target through remote SSH commands instead of ssh://\n    return runRemoteCommand(target, `type ${path}`);\n  }\n  throw err;\n}","preventionTips":["Maintain a list of Windows hosts and exclude them from ssh:// workflows","Use the bash tool with explicit remote commands for Windows targets","Confirm host OS classification if you believe it was misdetected"],"tags":["ssh","windows","platform","unsupported"],"backgroundTag":"ssh-remote-platform-unsupported","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}