jdx/mise · error

brew-cask: binary target '{}' must be under {}

Error message

brew-cask: binary target '{}' must be under {}

What it means

binary_target_path validates that a cask's binary symlink/stanza target resolves under one of the allowed root directories (e.g. prefix/bin, /usr/local/bin, /opt/homebrew/bin). If the target path is not under any allowed root (and is not rejected earlier for containing '..'), mise refuses the operation rather than writing a binary outside managed locations. This guards against casks that declare unusual binary destinations.

Source

Thrown at src/system/packages/brew/cask/paths.rs:305

    let target = if path.is_absolute() {
        path
    } else if target_name.contains('/') {
        prefix.join(path)
    } else {
        prefix.join("bin").join(path)
    };
    if target
        .components()
        .any(|component| matches!(component, Component::ParentDir))
    {
        bail!(
            "brew-cask: binary target '{}' must not contain '..'",
            target.display()
        );
    }
    let roots = allowed_binary_target_roots();
    if !roots.iter().any(|root| target.starts_with(root)) {
        bail!(
            "brew-cask: binary target '{}' must be under {}",
            target.display(),
            allowed_binary_target_roots_display(&roots)
        );
    }
    Ok(target)
}

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Inspect the cask's binary stanza and confirm the target directory is a standard Homebrew bin path
  2. Run `brew reinstall --cask <token>` so Homebrew itself places the binary correctly, then retry
  3. If the cask is wrong, fix or update the cask definition (brew tap-homebrew / cask edit) so targets fall under allowed roots
  4. Verify your Homebrew prefix matches allowed_binary_target_roots() expectations for your platform

Example fix

// before: cask stanza pointing outside allowed roots
binary "#{appdir}/MyTool.app/Contents/MacOS/mytool"
// after: target under the Homebrew prefix bin root, e.g.
binary "#{staged_path}/mytool"
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
fn is_under_allowed_root(target: &Path, roots: &[&Path]) -> bool {
    !target.components().any(|c| c.as_os_str() == "..")
        && roots.iter().any(|root| target.starts_with(root))
}

Prevention

When it happens

Trigger: Calling binary_target_path (via target_path or binary_targets_must_be_under_an_allowed_root) with a cask binary stanza target whose resolved path does not start with any root returned by allowed_binary_target_roots() — e.g. a cask installs its binary into /Applications or a custom prefix subdirectory.

Common situations: Installing an unusual third-party cask whose binary stanza points outside standard Homebrew bin directories; Homebrew prefix changes (Intel /usr/local vs Apple Silicon /opt/homebrew) leaving roots misaligned; hand-edited cask definitions.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/fbb3facb3a8f9cee. Report an issue: GitHub.