{"record":{"id":"870cab491e280ae0","repo":"herdrdev/herdr","slug":"failed-to-start-ssh-bridge-err","errorCode":null,"errorMessage":"failed to start ssh bridge: {err}","messagePattern":"failed to start ssh bridge: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/remote/attach.rs","lineNumber":1837,"sourceCode":"    target: &str,\n    remote_herdr: &RemoteHerdr,\n    session_name: &str,\n    ssh_options: Option<&ManagedSshOptions>,\n    _bridge_stop: &Arc<AtomicBool>,\n) -> io::Result<()> {\n    let mut command = Command::new(\"ssh\");\n    apply_managed_ssh_options(&mut command, ssh_options);\n    command\n        .arg(\"-T\")\n        .arg(target)\n        .arg(remote_bridge_command(remote_herdr, session_name))\n        .stdin(Stdio::piped())\n        .stdout(Stdio::piped())\n        .stderr(Stdio::inherit());\n\n    let mut child = command\n        .spawn()\n        .map_err(|err| io::Error::new(err.kind(), format!(\"failed to start ssh bridge: {err}\")))?;\n    let mut child_stdin = child\n        .stdin\n        .take()\n        .ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe, \"ssh bridge stdin missing\"))?;\n    let mut child_stdout = child\n        .stdout\n        .take()\n        .ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe, \"ssh bridge stdout missing\"))?;\n    let mut stream_to_child = stream.try_clone()?;\n    let mut child_to_stream = stream;\n\n    let upload = thread::spawn(move || {\n        let _ = copy_flush(&mut stream_to_child, &mut child_stdin);\n    });\n    let download = thread::spawn(move || {\n        let _ = copy_flush(&mut child_stdout, &mut child_to_stream);\n        let _ = crate::ipc::shutdown_local_stream_write(&child_to_stream);\n    });","sourceCodeStart":1819,"sourceCodeEnd":1855,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/remote/attach.rs#L1819-L1855","documentation":"Spawning the SSH bridge child process (with piped stdin/stdout and inherited stderr) failed; the OS spawn error is wrapped preserving its kind. This happens before any bridging starts, meaning the ssh command itself could not be launched.","triggerScenarios":"The ssh executable is missing from PATH, not executable, argument list issues, or process/resource limits preventing spawn when establishing the local-to-remote stdio bridge.","commonSituations":"Containers or minimal hosts without openssh-client, PATH stripped in non-interactive shells, fork failures under memory pressure.","solutions":["Verify ssh is installed: ssh -V","Install openssh-client on the local machine","Fix PATH for non-interactive environments (set it in the shell profile herdr inherits)","Retry when the machine is not under resource pressure"],"exampleFix":"# before: no ssh client\n# after\napt-get update && apt-get install -y openssh-client","handlingStrategy":"validation","validationCode":"fn ssh_available() -> bool {\n    std::process::Command::new(\"ssh\")\n        .arg(\"-V\")\n        .output()\n        .is_ok()\n}","typeGuard":null,"tryCatchPattern":"match attach() {\n    Err(e) if e.to_string().contains(\"failed to start ssh bridge\") => {\n        eprintln!(\"check that ssh is installed and on PATH\");\n        Err(e)\n    }\n    r => r,\n}","preventionTips":["Verify ssh -V works in the environment hosting herdr","Install openssh-client in container images that run attach"],"tags":["ssh","spawn","bridge","process","rust"],"backgroundTag":"ssh-process-spawn-failed","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}