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
- Check the allowed roots listed in the error message and rewrite the target under one of them (typically `$(brew --prefix)/...`)
- Use `$HOMEBREW_PREFIX` instead of a hardcoded absolute path so the target tracks the real prefix
- If Homebrew's actual prefix differs from the configured one, fix the prefix configuration so `prefix::prefix()` matches the real install
- 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
- Prefer `$HOMEBREW_PREFIX` over hardcoded absolute paths in target stanzas
- Confirm Homebrew's real prefix matches the configured one (`brew --prefix`)
- Keep cask binaries under the Homebrew prefix or /usr/local trees
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
- brew-cask: invalid appdir
- brew-cask: ' ' must be an absolute path
- brew-cask: ' ' must not resolve to the filesystem root
- brew-cask: app target contains NUL
- brew-cask: app target
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)