{"record":{"id":"36daa57054efea6a","repo":"sinelaw/fresh","slug":"sudo-tee-failed","errorCode":null,"errorMessage":"sudo tee failed: {}","messagePattern":"sudo tee failed: (.+?)","errorType":"exception","errorClass":"io::Error (PermissionDenied)","httpStatus":null,"severity":"error","filePath":"crates/fresh-editor-core/src/model/filesystem.rs","lineNumber":1528,"sourceCode":"        // Write data via sudo tee\n        let mut child = Command::new(\"sudo\")\n            .args([\"tee\", &path.to_string_lossy()])\n            .stdin(Stdio::piped())\n            .stdout(Stdio::null())\n            .stderr(Stdio::piped())\n            .hide_window()\n            .spawn()\n            .map_err(|e| io::Error::other(format!(\"failed to spawn sudo: {}\", e)))?;\n\n        if let Some(mut stdin) = child.stdin.take() {\n            use std::io::Write;\n            stdin.write_all(data)?;\n        }\n\n        let output = child.wait_with_output()?;\n        if !output.status.success() {\n            let stderr = String::from_utf8_lossy(&output.stderr);\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                format!(\"sudo tee failed: {}\", stderr.trim()),\n            ));\n        }\n\n        // Set permissions via sudo chmod\n        let status = Command::new(\"sudo\")\n            .args([\"chmod\", &format!(\"{:o}\", mode), &path.to_string_lossy()])\n            .hide_window()\n            .status()?;\n        if !status.success() {\n            return Err(io::Error::other(\"sudo chmod failed\"));\n        }\n\n        // Set ownership via sudo chown\n        let status = Command::new(\"sudo\")\n            .args([\n                \"chown\",","sourceCodeStart":1510,"sourceCodeEnd":1546,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor-core/src/model/filesystem.rs#L1510-L1546","documentation":"The privileged write path (save via `sudo tee`) fails when the spawned sudo tee process exits with non-zero status. The error carries the trimmed stderr from sudo/tee so the actual cause (password prompt failure, policy denial, unreadable path) is visible. Returned as PermissionDenied.","triggerScenarios":"Calling the elevated-save path when sudo requires a password on a non-tty, the user lacks sudo rights for the target, or the target file/directory is not writable even by root (read-only mount, immutable flag).","commonSituations":"Saving a root-owned file over SSH without a tty; sudoers NOPASSWD not configured for tee; editing files on a read-only filesystem.","solutions":["Run sudo -v first in an interactive terminal so credentials are cached, then retry the save.","Add a sudoers rule allowing tee for this user (e.g. user ALL=(root) NOPASSWD: /usr/bin/tee) or use a persistence helper.","Check the captured stderr in the message; if it's a read-only mount or 'Operation not permitted', fix filesystem permissions/attributes instead."],"exampleFix":"// before (non-interactive sudo fails with 'a password is required')\nsudo tee /etc/nginx/nginx.conf\n// after: cache credentials first, or grant NOPASSWD\nsudo -v && echo '...' | sudo tee /etc/nginx/nginx.conf","handlingStrategy":"retry","validationCode":"// check sudo availability before attempting elevated save\nif !std::process::Command::new(\"sudo\").arg(\"-n\").arg(\"true\").status().map(|s| s.success()).unwrap_or(false) {\n    eprintln!(\"sudo requires a password; run `sudo -v` first\");\n}","typeGuard":null,"tryCatchPattern":"match save_with_sudo(path, data) {\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {\n    eprintln!(\"elevated save failed: {e}; run `sudo -v` and retry\");\n    // retry once after credential refresh\n    }\n    other => other?,\n}","preventionTips":["Cache sudo credentials with `sudo -v` before saving","Configure NOPASSWD sudoers entry for tee if using elevated saves routinely","Read the stderr in the error message to distinguish password, policy, and filesystem causes"],"tags":["permissions","sudo","io"],"backgroundTag":"permission-denied","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}