{"record":{"id":"3ea2a1b5e52a7d9d","repo":"jdx/mise","slug":"brew-cask-staging-directory-is-not-owned-by-the-c","errorCode":null,"errorMessage":"brew-cask: staging directory is not owned by the current user","messagePattern":"brew-cask: staging directory is not owned by the current user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":2595,"sourceCode":"        )\n    })?;\n    let destination = nix::fcntl::openat(\n        &dir,\n        name,\n        nix::fcntl::OFlag::O_RDONLY\n            | nix::fcntl::OFlag::O_DIRECTORY\n            | nix::fcntl::OFlag::O_NOFOLLOW,\n        nix::sys::stat::Mode::empty(),\n    )\n    .wrap_err_with(|| {\n        format!(\n            \"brew-cask: cannot open staging directory {}\",\n            Path::new(name).display()\n        )\n    })?;\n    let stat = nix::sys::stat::fstat(&destination)?;\n    if stat.st_uid != nix::unistd::geteuid().as_raw() {\n        bail!(\"brew-cask: staging directory is not owned by the current user\");\n    }\n    // `ditto src dst` copies the *contents* of src into dst, so pointing it at\n    // the bound directory reproduces the bundle in place.\n    let status = run_in_trusted_dir(\n        \"ditto\",\n        &[from.as_os_str(), std::ffi::OsStr::new(\".\")],\n        &destination,\n    )?;\n    if !status.success() {\n        bail!(\n            \"ditto failed copying {} to {}\",\n            from.display(),\n            Path::new(name).display()\n        );\n    }\n    // Restore the bundle's own permissions, which the private staging mode hid.\n    if let Ok(metadata) = from.symlink_metadata() {\n        use std::os::unix::fs::PermissionsExt;","sourceCodeStart":2577,"sourceCodeEnd":2613,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/packages/brew/cask.rs#L2577-L2613","documentation":"To ditto a bundle into the staging destination safely, mise opens the destination with O_NOFOLLOW/O_DIRECTORY and then fstats it, requiring st_uid to equal the effective uid. Writing through a directory owned by a different user would let that owner influence the copied bundle, so the operation is refused.","triggerScenarios":"The staging directory (or an ancestor left in the Caskroom) is owned by root because a previous run used sudo while the current run is unprivileged, or the reverse; Caskroom ownership changed outside mise.","commonSituations":"Mixing sudo and non-sudo cask installs; brew permission-repair tools rewriting Caskroom ownership; Caskroom copied or restored with different ownership.","solutions":["Take ownership of the staging tree: sudo chown -R \"$(whoami)\" <Caskroom> (or at least the staging parent named in the error)","Or delete the stale staging directory and let the next run recreate it","Pick one identity (always sudo, or never) for cask operations and stay consistent"],"exampleFix":"# before -- earlier sudo run left root-owned staging dirs\nsudo ls -ld /opt/homebrew/Caskroom/staging\n\n# after\nsudo chown -R \"$(whoami)\" /opt/homebrew/Caskroom\n# or start clean\nsudo rm -rf /opt/homebrew/Caskroom/staging","handlingStrategy":"validation","validationCode":"use std::os::unix::fs::MetadataExt;\n\nfn staging_dir_owned_by_me(dir: &std::path::Path) -> bool {\n    std::fs::metadata(dir)\n        .map(|m| m.uid() == unsafe { libc::geteuid() } as u32)\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match stage_bundle(from, dir) {\n    Err(e) if e.to_string().contains(\"not owned by the current user\") => {\n        eprintln!(\"remediate with: sudo chown -R \\\"$(whoami)\\\" <staging parent>, then retry\");\n        return Err(e);\n    }\n    other => other?,\n}","preventionTips":["Use one identity (sudo or non-sudo) consistently for all cask operations","Fix Caskroom ownership after permission-repair tools or restores","Delete stale staging dirs instead of reusing them across identities"],"tags":["brew-cask","ownership","staging","permissions"],"backgroundTag":"file-ownership-mismatch","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}