{"record":{"id":"670960f595a957d4","repo":"can1357/oh-my-pi","slug":"failed-to-start-ssh-master-for-target-detail","errorCode":null,"errorMessage":"Failed to start SSH master for ${target}${detail}","messagePattern":"Failed to start SSH master for (.+?)(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/ssh/connection-manager.ts","lineNumber":775,"sourceCode":"\t\t\tif (!hostInfoCache.has(key) && !(await loadHostInfoFromDisk(host))) {\n\t\t\t\tawait probeHostInfo(host);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst check = await runSshSync([\"-O\", \"check\", ...buildCommonArgs(host), target]);\n\t\tif (check.exitCode === 0) {\n\t\t\tactiveHosts.set(key, host);\n\t\t\tif (!hostInfoCache.has(key) && !(await loadHostInfoFromDisk(host))) {\n\t\t\t\tawait probeHostInfo(host);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst start = await runSshSync([\"-M\", \"-N\", \"-f\", ...buildCommonArgs(host), target]);\n\t\tif (start.exitCode !== 0) {\n\t\t\tconst detail = start.stderr ? `: ${start.stderr}` : \"\";\n\t\t\tthrow new Error(`Failed to start SSH master for ${target}${detail}`);\n\t\t}\n\n\t\tactiveHosts.set(key, host);\n\t\tif (!hostInfoCache.has(key) && !(await loadHostInfoFromDisk(host))) {\n\t\t\tawait probeHostInfo(host);\n\t\t}\n\t})();\n\n\tpendingConnections.set(key, promise);\n\ttry {\n\t\tawait promise;\n\t} finally {\n\t\tpendingConnections.delete(key);\n\t}\n}\n\nexport async function invalidateHostMetadata(hostNames: Iterable<string>): Promise<void> {\n\tconst names = [...hostNames];","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/ssh/connection-manager.ts#L757-L793","documentation":"The manager opens a ControlMaster (`ssh -M -N -f`) to multiplex connections over one authenticated socket. If that master process exits non-zero, this error is thrown, appending the master's stderr for diagnosis. It wraps whatever underlying ssh failure occurred (auth, DNS, timeout, refused connection).","triggerScenarios":"runSshSync([\"-M\",\"-N\",\"-f\",...]) returning non-zero: unreachable host/port, authentication failure, ControlPersist/socket path issues, or the remote refusing sessions.","commonSituations":"Wrong host/port in config, key not authorized on remote (Permission denied (publickey)), VPN not connected, host DNS changed, too many concurrent masters on a flaky network.","solutions":["Read the appended stderr detail — it usually says the root cause (connection refused, timeout, permission denied)","Test manually: ssh -M -N -f <host> with the same key/config","Verify host/port reachability: ping/nc -vz <host> 22","Confirm the key is authorized: ssh-copy-id <host> or check authorized_keys","Check ~/.ssh/config and any per-target overrides for wrong User/Port/IdentityFile"],"exampleFix":"// before\n{ name: \"prod\", host: \"10.0.0.99\", port: 22 } // host offline -> master fails\n// after: fix host or connect VPN first\n{ name: \"prod\", host: \"10.0.0.5\", port: 22 }","handlingStrategy":"retry","validationCode":"import { $ } from \"bun\";\n// preflight: plain ssh reachability before attempting master\nconst probe = await $`ssh -o BatchMode=yes -o ConnectTimeout=5 ${target} true`.quiet().nothrow();\nif (probe.exitCode !== 0) console.error(\"ssh target unreachable/auth failing:\", probe.stderr.toString());","typeGuard":null,"tryCatchPattern":"try {\n  await connect(target);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Failed to start SSH master for\")) {\n    const detail = err.message.split(\": \").slice(1).join(\": \");\n    if (/timeout|Connection refused|unreachable/i.test(detail)) {\n      await Bun.sleep(1000); // retry with backoff for transient network\n      return connect(target);\n    }\n    if (/permission denied|publickey/i.test(detail)) console.error(\"Fix key auth (ssh-copy-id)\");\n  }\n  throw err;\n}","preventionTips":["Test `ssh <host> true` manually before automating","Use ssh-copy-id to install keys","Connect VPN before reaching internal hosts","Keep ~/.ssh/config Host entries consistent with tool targets"],"tags":["ssh","network","connection","controlmaster"],"backgroundTag":"ssh-master-start-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}