jdx/mise · error

brew-cask: binary target

Error message

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

What it means

This error is thrown by `binary_target_path` in src/system/packages/brew/cask/paths.rs when a resolved binary target path is not under any of the allowed binary target roots (`allowed_binary_target_roots()`, e.g. Homebrew prefix trees and /usr/local). After passing the `..` check, the library requires every cask binary to be linked inside one of these sanctioned trees, and the error message lists the acceptable roots.

Solutions

  1. Check the allowed roots listed in the error message and rewrite the target under one of them (typically `$(brew --prefix)/...`)
  2. Use `$HOMEBREW_PREFIX` instead of a hardcoded absolute path so the target tracks the real prefix
  3. If Homebrew's actual prefix differs from the configured one, fix the prefix configuration so `prefix::prefix()` matches the real install
  4. Symlink the external binary into an allowed tree and reference that link instead

Example fix

// before
binary_target_path("/opt/mytools/tool", &appdir)
// error: binary target '/opt/mytools/tool' must be under ...

// after
binary_target_path("$HOMEBREW_PREFIX/opt/mytools/bin/tool", &appdir)
Defensive patterns

Strategy: validation

Validate before calling

fn target_is_under_allowed_roots(target: &std::path::Path) -> bool {
    allowed_binary_target_roots().iter().any(|root| target.starts_with(root))
}

Type guard

fn confined_target(t: &str) -> Option<std::path::PathBuf> {
    binary_target_path(t, appdir).ok().filter(|p| target_is_under_allowed_roots(p))
}

Try / catch

match binary_target_path(target_name, &appdir) {
    Ok(path) => use(path),
    Err(e) if e.to_string().contains("must be under") => relocate_target_under_allowed_root(target_name),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `binary_target_path(target_name, appdir)` with an absolute target (or one expanded from `$HOMEBREW_PREFIX`) that does not `starts_with` any allowed root — e.g. an absolute path like `/opt/tools/foo`, or a `$HOMEBREW_PREFIX` substitution pointing outside the expected prefix when the configured prefix differs from the actual install location. Reached via `target_path` or `binary_targets_must_stay_under_an_allowed_root`.

Common situations: A cask formula hardcodes an absolute install path outside Homebrew's trees; the user's Homebrew is installed in a non-standard prefix while the formula assumed the default; a hand-edited stanza points at `/usr/bin` or `/Applications` binaries; moving Homebrew between machines with stale absolute paths.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: 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 533346cc37)