jdx/mise · error
brew-cask: staging directory is not owned by the current use
Error message
brew-cask: staging directory is not owned by the current user
What it means
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.
Source
Thrown at src/system/packages/brew/cask.rs:2595
)
})?;
let destination = nix::fcntl::openat(
&dir,
name,
nix::fcntl::OFlag::O_RDONLY
| nix::fcntl::OFlag::O_DIRECTORY
| nix::fcntl::OFlag::O_NOFOLLOW,
nix::sys::stat::Mode::empty(),
)
.wrap_err_with(|| {
format!(
"brew-cask: cannot open staging directory {}",
Path::new(name).display()
)
})?;
let stat = nix::sys::stat::fstat(&destination)?;
if stat.st_uid != nix::unistd::geteuid().as_raw() {
bail!("brew-cask: staging directory is not owned by the current user");
}
// `ditto src dst` copies the *contents* of src into dst, so pointing it at
// the bound directory reproduces the bundle in place.
let status = run_in_trusted_dir(
"ditto",
&[from.as_os_str(), std::ffi::OsStr::new(".")],
&destination,
)?;
if !status.success() {
bail!(
"ditto failed copying {} to {}",
from.display(),
Path::new(name).display()
);
}
// Restore the bundle's own permissions, which the private staging mode hid.
if let Ok(metadata) = from.symlink_metadata() {
use std::os::unix::fs::PermissionsExt;View on GitHub (pinned to 9dcfcaa0dc)
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
Example fix
# before -- earlier sudo run left root-owned staging dirs sudo ls -ld /opt/homebrew/Caskroom/staging # after sudo chown -R "$(whoami)" /opt/homebrew/Caskroom # or start clean sudo rm -rf /opt/homebrew/Caskroom/staging
Defensive patterns
Strategy: validation
Validate before calling
use std::os::unix::fs::MetadataExt;
fn staging_dir_owned_by_me(dir: &std::path::Path) -> bool {
std::fs::metadata(dir)
.map(|m| m.uid() == unsafe { libc::geteuid() } as u32)
.unwrap_or(false)
} Try / catch
match stage_bundle(from, dir) {
Err(e) if e.to_string().contains("not owned by the current user") => {
eprintln!("remediate with: sudo chown -R \"$(whoami)\" <staging parent>, then retry");
return Err(e);
}
other => other?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Mixing sudo and non-sudo cask installs; brew permission-repair tools rewriting Caskroom ownership; Caskroom copied or restored with different ownership.
Related errors
- brew-cask: refusing operation through untrusted directory {}
- install from exe
- mise outdated --monorepo is not implemented yet
- mise prune --monorepo is not implemented yet
- brew-cask: temporary artifact directory is not private
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/3ea2a1b5e52a7d9d.
Report an issue: GitHub.