{"record":{"id":"5c090363fbacb3a0","repo":"zeroclaw-labs/zeroclaw","slug":"cli-update-not-writable","errorCode":"cli-update-not-writable","errorMessage":"install directory {$dir} is not writable ({$error}); re-run `zeroclaw update` with elevated privileges (sudo on macOS/Linux, an Administrator console on Windows)","messagePattern":"install directory (.+?) is not writable \\((.+?)\\); re-run `zeroclaw update` with elevated privileges \\(sudo on macOS/Linux, an Administrator console on Windows\\)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/commands/update.rs","lineNumber":840,"sourceCode":"        Some(\"x86\")\n    } else if cfg!(target_arch = \"arm\") {\n        Some(\"arm\")\n    } else {\n        None\n    }\n}\n\nasync fn ensure_install_dir_writable(exe: &Path) -> Result<()> {\n    let dir = exe\n        .parent()\n        .context(\"cannot determine install directory for the current executable\")?;\n    let probe = dir.join(format!(\".zeroclaw-update-probe-{}\", std::process::id()));\n    match tokio::fs::File::create(&probe).await {\n        Ok(_) => {\n            let _ = tokio::fs::remove_file(&probe).await;\n            Ok(())\n        }\n        Err(e) => bail!(install_dir_not_writable_message(\n            &dir.display().to_string(),\n            &e.to_string()\n        )),\n    }\n}\n\n#[cfg(not(windows))]\nasync fn swap_binary(new: &Path, target: &Path) -> Result<()> {\n    tokio::fs::remove_file(target)\n        .await\n        .context(\"failed to remove old binary\")?;\n    tokio::fs::copy(new, target)\n        .await\n        .context(\"failed to write new binary\")?;\n    Ok(())\n}\n\n#[cfg(windows)]","sourceCodeStart":822,"sourceCodeEnd":858,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/src/commands/update.rs#L822-L858","documentation":"Before installing an update, ensure_install_dir_writable probes the install directory by creating a '.zeroclaw-update-probe-<pid>' file and deleting it. If creation fails, the update aborts with the directory, the underlying OS error, and the remediation hint to re-run with sudo (macOS/Linux) or an Administrator console (Windows). This error carries the stable code 'cli-update-not-writable'.","triggerScenarios":"`zeroclaw update` when the directory holding the current zeroclaw binary is not writable by the invoking user: binary in /usr/local/bin owned by root, a read-only mount, a system-protected path, or (ENOENT variants) an install directory that no longer exists.","commonSituations":"Binary initially installed with sudo or by a package manager into a root-owned path; corporate lockdown with read-only /usr/local; running the update from an unprivileged service account.","solutions":["Re-run the update with elevated privileges exactly as the message suggests: `sudo zeroclaw update` on macOS/Linux or an Administrator console on Windows.","For a user-owned setup instead: `sudo chown $(whoami) <install-dir>` so future updates need no elevation.","Or move the binary to a user-writable directory already on PATH (e.g. ~/.local/bin) and update from there.","If you expected the directory to be writable, check the embedded OS error for the real cause (read-only mount, deleted directory, ACL)."],"exampleFix":"# before: unprivileged update into root-owned dir fails\nzeroclaw update   # -> install directory ... is not writable\n# after: elevate, or take ownership once\nsudo zeroclaw update\nsudo chown $(whoami) /usr/local/bin && zeroclaw update","handlingStrategy":"validation","validationCode":"use std::fs;\nfn install_dir_writable(dir: &std::path::Path) -> bool {\n    let probe = dir.join(format!(\".zc-probe-{}\", std::process::id()));\n    match fs::File::create(&probe) {\n        Ok(_) => { let _ = fs::remove_file(&probe); true }\n        Err(_) => false,\n    }\n}\n// call before running the update; if false, elevate or fix ownership first","typeGuard":null,"tryCatchPattern":"match run_update().await {\n    Err(e) if e.to_string().contains(\"is not writable\") => {\n        // re-invoke with sudo (or fix dir ownership), then retry once\n    }\n    other => other,\n}","preventionTips":["Install zeroclaw in a user-writable directory on PATH (~/.local/bin) to avoid elevation on every update.","Or chown the install directory once: `sudo chown $(whoami) <dir>`.","In automation, pre-check writability with a probe file before invoking the update command."],"tags":["update","permissions","install","filesystem","sudo"],"backgroundTag":"permission-denied","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}