{"record":{"id":"3ccc9d19a231201a","repo":"herdrdev/herdr","slug":"remote-client-exited-with-status","errorCode":null,"errorMessage":"remote client exited with {status}","messagePattern":"remote client exited with (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/remote/attach.rs","lineNumber":2138,"sourceCode":"    let status = Command::new(exe)\n        .arg(\"client\")\n        .env(\n            crate::server::socket_paths::CLIENT_SOCKET_PATH_ENV_VAR,\n            local_socket,\n        )\n        .env(\"HERDR_RENDER_ENCODING\", \"terminal-ansi\")\n        .env(REATTACH_COMMAND_ENV_VAR, reattach_command)\n        .env(REMOTE_KEYBINDINGS_ENV_VAR, keybindings.as_str())\n        .env_remove(crate::api::SOCKET_PATH_ENV_VAR)\n        .stdin(Stdio::inherit())\n        .stdout(Stdio::inherit())\n        .stderr(Stdio::inherit())\n        .status()?;\n\n    if status.success() {\n        Ok(())\n    } else {\n        Err(io::Error::new(\n            io::ErrorKind::Interrupted,\n            format!(\"remote client exited with {status}\"),\n        ))\n    }\n}\n\nfn local_forward_socket_path(target: &str, session_name: &str) -> PathBuf {\n    let pid = std::process::id();\n    let target_clean = sanitize_path_component(target);\n    let session_clean = sanitize_path_component(session_name);\n    let readable_name = format!(\"herdr-remote-{pid}-{target_clean}-{session_clean}.sock\");\n    let target_prefix: String = target_clean.chars().take(8).collect();\n    let hash = short_socket_hash(target, session_name);\n    let short_name = format!(\"herdr-r-{pid}-{target_prefix}-{hash}.sock\");\n    crate::platform::remote_bridge_endpoint_path(&readable_name, &short_name)\n}\n\n#[cfg(all(test, unix))]","sourceCodeStart":2120,"sourceCodeEnd":2156,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/remote/attach.rs#L2120-L2156","documentation":"The spawned remote client process (e.g. an SSH-attached herdr client) exited with a non-success status code. The wrapper rethrows it as io::ErrorKind::Interrupted with the process's ExitStatus formatted into the message. It means the remote side of an attach session terminated abnormally.","triggerScenarios":"Calling the remote attach helper that spawns a child herdr client with inherited stdio and checking status.success(); any nonzero exit code or signal termination of that child produces this error.","commonSituations":"SSH connection dropped mid-session, remote herdr binary missing or crashing, remote shell exiting due to auth failure, or the remote client hitting its own fatal error.","solutions":["Check the child's exit status in the message (exit code vs signal) to identify crash vs clean nonzero exit","Run the remote client command manually over ssh to see its stderr","Verify the remote herdr binary exists and is a compatible version","Check network/SSH stability if the status indicates signal termination (e.g. SIGKILL/SIGTERM)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match attach_result { Ok(()) => {}, Err(e) if e.kind() == io::ErrorKind::Interrupted && e.to_string().contains(\"remote client exited\") => { tracing::warn!(\"remote attach ended: {e}\"); }, Err(e) => return Err(e) }","preventionTips":["Treat remote client exit as an expected detach, not a fatal error","Log the child's stderr (inherited) for post-mortem","Keep SSH keepalives configured for long remote sessions"],"tags":["remote","process-exit","ssh","attach"],"backgroundTag":"subprocess-nonzero-exit","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}