{"record":{"id":"9e266abc0d85b194","repo":"jdx/mise","slug":"remote-cleanup-failed-with-status","errorCode":null,"errorMessage":"remote cleanup failed with {status}","messagePattern":"remote cleanup failed with (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/system/remote.rs","lineNumber":2107,"sourceCode":"                    shell_quote(remote)\n                ),\n            ],\n            file,\n        )\n        .await\n    }\n\n    async fn cleanup(&self, path: &str) -> Result<()> {\n        validate_staging_path(path)?;\n        let mut command = tokio::process::Command::new(&self.ssh);\n        command\n            .args(self.args(false, &[\"rm\", \"-rf\", \"--\", path]))\n            .kill_on_drop(true);\n        let status = tokio::time::timeout(std::time::Duration::from_secs(5), command.status())\n            .await\n            .map_err(|_| eyre!(\"remote cleanup timed out\"))??;\n        if !status.success() {\n            bail!(\"remote cleanup failed with {status}\");\n        }\n        Ok(())\n    }\n\n    async fn close(&self) {\n        let Some(control_path) = &self.control_path else {\n            return;\n        };\n        let mut command = tokio::process::Command::new(&self.ssh);\n        command\n            .kill_on_drop(true)\n            .args([\"-S\"])\n            .arg(control_path)\n            .args([\"-O\", \"exit\"])\n            .arg(self.host.destination())\n            .stdout(Stdio::null())\n            .stderr(Stdio::null());\n        let status =","sourceCodeStart":2089,"sourceCodeEnd":2125,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote.rs#L2089-L2125","documentation":"The remote cleanup step runs `ssh host rm -rf -- <path>` wrapped in a 5-second timeout and bails if the remote `rm` exits non-success. This is a best-effort delete of the bootstrap staging directory, so failure means the temp artifact may be left behind on the remote host.","triggerScenarios":"The `rm -rf` command on the remote host returns non-zero within the 5s window: permission denied on the staging dir, remote shell failure, or the command being killed at the 5s timeout... though the timeout case surfaces as 'remote cleanup timed out'; this error is specifically a non-success exit status.","commonSituations":"Slow/high-latency SSH connection making rm appear to fail or hang; staging path owned by another user after a partial bootstrap; remote account restricted (rbash, limited sudo).","solutions":["SSH in manually and remove the staging directory: `ssh host 'rm -rf /tmp/mise-bootstrap.*'`","Check ownership/permissions of the staging dir and remove as the correct user or with elevated rights","Increase tolerance for slow links by ensuring SSH connection reuse (ControlMaster) so subsequent commands are fast"],"exampleFix":"// before\n# leftover staging dir owned by root\nssh host 'ls -ld /tmp/mise-bootstrap.*'  # root:root\n// after\nssh host 'sudo rm -rf /tmp/mise-bootstrap.*'  # or fix ownership first","handlingStrategy":"try-catch","validationCode":"# ensure cleanup will succeed: session owns the staging dir\nssh \"$host\" \"test -O \\\\\"$staging\\\\\" && rm -rf -- \\\\\"$staging\\\\\"\"","typeGuard":null,"tryCatchPattern":"if let Err(e) = cleanup().await {\n    // non-fatal: log leftover path for manual removal\n    eprintln!(\"warning: {e}; leftover /tmp/mise-bootstrap.* may remain on host\");\n}","preventionTips":["Run bootstrap as a single user so staging dirs stay owned by it","Treat cleanup failure as best-effort; sweep leftovers periodically","Enable SSH connection reuse to keep short commands fast"],"tags":["remote","ssh","cleanup","process-exit"],"backgroundTag":"command-failed","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}