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

  1. Re-run the mise command; if Homebrew completed the install, mise will adopt/see the Homebrew-managed state instead of failing.
  2. Stop concurrent Homebrew activity (brew autoupdate, scheduled brew bundle/upgrade) before running mise package operations.
  3. 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

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


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)