jdx/mise · error
brew-cask: : Homebrew took ownership of this cask while…
Error message
brew-cask:{token}: Homebrew took ownership of this cask while installation was pending What it means
While mise was installing a cask into its own staging directory, Homebrew's .metadata marker appeared for that token, meaning Homebrew performed its own install/upgrade of the same cask concurrently. mise detects the ownership race, deletes its staging directory, and aborts rather than fighting Homebrew for ownership of the Caskroom.
Solutions
- Re-run the mise command; if Homebrew completed the install, mise will adopt/see the Homebrew-managed state instead of failing.
- Stop concurrent Homebrew activity (brew autoupdate, scheduled brew bundle/upgrade) before running mise package operations.
- Verify the cask's state with `brew list --cask <token>` and retry once no other brew process is running.
Example fix
// before: brew autoupdate racing mise $ brew autoupdate start --immediate $ mise pkg install cask:google-chrome # ERROR: Homebrew took ownership // after: pause background brew during mise operations $ brew autoupdate stop $ mise pkg install cask:google-chrome # ok
Defensive patterns
Strategy: retry
Validate before calling
// before installing, ensure no concurrent brew process holds the token
let out = std::process::Command::new("pgrep").args(["-f", "brew .*(install|upgrade|bundle)"]).output()?;
if out.status.success() { /* defer operation */ } Try / catch
match result {
Err(e) if e.to_string().contains("took ownership") => {
// Homebrew won the race; adopt its state and retry
retry_with_backoff(3)
}
r => r,
} Prevention
- Disable brew autoupdate or scheduled brew bundle during mise runs.
- Serialize all package-manager operations in CI (mutex/lock).
- Re-run mise after the error; Homebrew's completed install is usually usable.
When it happens
Trigger: ensure_homebrew_did_not_take_ownership(token, stage) is called at the end of install_one_with_ancestors and finds homebrew_metadata_present(token) is true after staging. This is the race guarded by tests ownership_race_guard_removes_only_mise_stage and ownership_race_probe_error_removes_mise_stage.
Common situations: A background `brew bundle`/`brew upgrade` (or brew autoupdate service) installed or upgraded the same cask while a mise operation was in flight; another terminal or CI job ran brew concurrently.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- ownership receipt has changed
- app target is outside an allowed Applications directory
- artifact target has changed
- binary target is not an owned Caskroom symlink
- brew-cask: : cask metadata has no sha256
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/53632fc30dd7ce88.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/state.rs:108
),
}
}
pub(super) fn ensure_homebrew_did_not_take_ownership(token: &str, stage: &Path) -> Result<()> {
let metadata_present = match homebrew_metadata_present(token) {
Ok(present) => present,
Err(err) => {
file::remove_all(stage).wrap_err_with(|| {
format!(
"failed to remove mise stage after Homebrew ownership check failed: {err:#}"
)
})?;
return Err(err);
}
};
if metadata_present {
file::remove_all(stage)?;
bail!(
"brew-cask:{token}: Homebrew took ownership of this cask while installation was pending"
);
}
Ok(())
}
pub(super) fn homebrew_metadata_present(token: &str) -> Result<bool> {
let path = caskroom_token_dir(token).join(".metadata");
match path.symlink_metadata() {
Ok(_) => Ok(true),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(false),
Err(err) => Err(err).wrap_err_with(|| {
format!(
"brew-cask:{token}: failed to inspect Homebrew metadata at '{}'",
path.display()
)
}),
}View on GitHub (pinned to 533346cc37)