jdx/mise · error

brew-cask: : Homebrew took ownership of this cask while…

Error message

brew-cask:{}: Homebrew took ownership of this cask while installation was pending

What it means

A TOCTOU re-check in install_one_with_ancestors (src/system/packages/brew/cask.rs:533): after fetch_and_stage (network download + extraction, which happens before the caskroom lock is taken), mise re-runs homebrew_metadata_present under the caskroom lock. If Homebrew claimed the cask in the meantime, the staged tree is deleted and the install aborts so brew and mise never both write the caskroom.

Solutions

  1. Decide who owns the cask: if Homebrew should not, run brew uninstall --cask <token>, then re-run the mise install serially
  2. Serialize brew and mise installs of the same cask — never run them concurrently
  3. Once ownership is consistent, a plain retry succeeds; the staged tree was already cleaned up by mise itself
Defensive patterns

Strategy: retry

Try / catch

Catch the error, run `brew list --cask <token>` to confirm the takeover, `brew uninstall --cask <token>` if mise should own it, then retry the install serially — at most once.

Prevention

When it happens

Trigger: Concurrently running brew install --cask X (or brew bundle / brew upgrade) while mise install of the same token is in its download/extract phase; the earlier ownership check passed, the later one catches the takeover.

Common situations: Dotfile bootstraps that parallelize brew and mise provisioning; CI steps racing a Homebrew bundle against mise system-package setup; scheduled brew auto-update jobs firing mid-install.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/5a928da20b6f0530. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/brew/cask.rs:533

                    completion.source
                );
            }
            for generated in &artifacts.generated_completions {
                miseprintln!("generate completions from {}", generated.executable);
            }
            return Ok(cask.version);
        }
        prefix::bootstrap(false)?;
        let stage = fetch_and_stage(&cask, pr).await?;
        let adopt = manager_options.brew_cask_adopt(&cask.token) && installed_version.is_none();
        if adopt && !cask.auto_updates {
            validate_adoptable_apps(&stage, &artifacts.apps)?;
        }
        let _caskroom_lock = lock_caskroom()?;
        recover_flight_backups()?;
        if homebrew_metadata_present(&cask.token) {
            file::remove_all(&stage)?;
            bail!(
                "brew-cask:{}: Homebrew took ownership of this cask while installation was pending",
                cask.token
            );
        }
        if let Some(version) = installed_cask_version(&cask, &artifacts)?
            && (cask.auto_updates || version == cask.version)
        {
            file::remove_all(stage)?;
            return Ok(version);
        }
        let previous_binaries = previous_binary_targets(&cask)?;
        let previous_fonts = previous_font_targets(&cask)?;
        let previous_completions = previous_completion_targets(&cask)?;
        let previous_flight_symlinks = previous_flight_symlink_targets(&cask)?;
        let previous_flight_directories = previous_flight_directory_targets(&cask)?;
        let previous_generic = previous_generic_targets(&cask)?;
        let caskroom_token = caskroom_token_dir(&cask.token);
        let caskroom = caskroom_version_dir(&cask.token, &cask.version);

View on GitHub (pinned to 6f52dcdf99)