jdx/mise · error · eyre::Report

binary target is not an owned Caskroom symlink: {}

Error message

binary target is not an owned Caskroom symlink: {}

What it means

Binary targets are expected to be symlinks living under the brew prefix's binary roots whose resolution stays inside the cask's Caskroom version directory. The prune path only removes links that provably point at the version being deleted; a real file, a relocated link, or a link under an unexpected root fails this check.

Source

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

            })
        {
            bail!(
                "app target is outside an allowed Applications directory: {}",
                path.display()
            );
        }
    }
    for path in &receipt.binaries {
        let record = records
            .get(path)
            .ok_or_else(|| eyre!("missing binary target record"))?;
        if record.fingerprint.kind != CaskTargetKind::Symlink
            || !allowed_binary_target_roots()
                .iter()
                .any(|root| path_is_below(path, root))
            || !symlink_resolves_below(path, &candidate.version_dir)
        {
            bail!(
                "binary target is not an owned Caskroom symlink: {}",
                path.display()
            );
        }
    }
    for path in &receipt.fonts {
        let record = records
            .get(path)
            .ok_or_else(|| eyre!("missing font target record"))?;
        let fonts = font_dir();
        if record.fingerprint.kind != CaskTargetKind::File
            || !path_is_below(path, &fonts)
            || !path.strip_prefix(&fonts).is_ok_and(|relative| {
                staged_target_matches(record, &candidate.version_dir.join(relative))
            })
        {
            bail!(
                "font target is outside the platform font directory: {}",

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Recreate the link so it points into the cask's Caskroom version dir: ln -sfn <prefix>/Caskroom/<token>/<version>/<binary> <prefix>/bin/<binary>
  2. Reinstall the cask to restore both the staged artifact and the link, then prune
  3. If the binary was deliberately replaced, uninstall the cask manually (remove the file and the Caskroom dir yourself)

Example fix

# before: link replaced by a real file
ls -l /opt/homebrew/bin/mytool   # regular file, not a symlink

# after: point it back at the cask's staged artifact
ln -sfn /opt/homebrew/Caskroom/mytool/1.2.3/mytool /opt/homebrew/bin/mytool
Defensive patterns

Strategy: validation

Validate before calling

// Before pruning, check each binary is a symlink resolving into its cask's
// version dir.
fn binary_owned_by_cask(path: &Path, version_dir: &Path) -> bool {
    std::fs::symlink_metadata(path)
        .is_ok_and(|m| m.file_type().is_symlink())
        && symlink_resolves_below(path, version_dir)
}

Type guard

fn is_owned_caskroom_symlink(path: &Path, version_dir: &Path) -> bool {
    path.symlink_metadata().map(|m| m.file_type().is_symlink()).unwrap_or(false)
        && symlink_resolves_below(path, version_dir)
}

Try / catch

// Skipped-cask pattern from apply: warn and continue with the rest of the plan.
if let Err(reason) = validate_cask_prune_candidate(candidate).and_then(|_| validate_cask_prune_claims(candidate)) {
    warn!("brew-cask:{}: skipped because recorded artifacts changed after planning: {reason:#}", candidate.token);
    continue;
}

Prevention

When it happens

Trigger: validate_cask_prune_candidate, binaries loop: fingerprint kind != Symlink, path not below allowed_binary_target_roots() (e.g. <prefix>/bin), or symlink_resolves_below(path, version_dir) false. Happens when the user replaced the symlink with a copied binary, relinked it to another cellar, or brew's own relink changed the target.

Common situations: User ran 'cp' over a stub or replaced a link with a real executable to 'fix' something; Homebrew reinstalled/linked its own version over the link; PATH shim tools rewiring the link; symlink target deleted first.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/a711072321e6fc15. Report an issue: GitHub.