jdx/mise · error
brew-cask: invalid appdir '{}'
Error message
brew-cask: invalid appdir '{}' What it means
A cask `binary` target written as `$APPDIR/<rel>` is joined to the appdir in use; that appdir must be one of the allowed app-dir roots (`/Applications` by default, the APP_DIR override, or the Homebrew prefix's Applications dir). `binary_target_path` rejects a `$APPDIR/...` target when the supplied appdir is not in that allowlist, preventing binaries from being linked into arbitrary directories via the appdir parameter.
Source
Thrown at src/system/packages/brew/cask/paths.rs:276
}
pub(super) fn allowed_binary_target_roots_display(roots: &[PathBuf]) -> String {
roots
.iter()
.map(|root| root.display().to_string())
.collect::<Vec<_>>()
.join(" or ")
}
pub(super) fn binary_target_path(target_name: &str, appdir: &Path) -> Result<PathBuf> {
if target_name.contains('\0') {
bail!("brew-cask: binary target contains NUL");
}
if let Some(relative) = target_name.strip_prefix("$APPDIR/") {
let relative = Path::new(relative);
reject_appdir_escape(relative, "binary $APPDIR target", target_name)?;
if !allowed_appdir_roots()?.iter().any(|root| root == appdir) {
bail!("brew-cask: invalid appdir '{}'", appdir.display());
}
return Ok(appdir.join(relative));
}
if target_name.contains("$APPDIR") {
bail!("brew-cask: $APPDIR must prefix a binary target");
}
let prefix = prefix::prefix();
let prefix_str = prefix.to_string_lossy();
let target_name = target_name.replace("$HOMEBREW_PREFIX", prefix_str.as_ref());
let path = PathBuf::from(&target_name);
let target = if path.is_absolute() {
path
} else if target_name.contains('/') {
prefix.join(path)
} else {
prefix.join("bin").join(path)
};
if targetView on GitHub (pinned to afd2eddd3a)
Solutions
- Pass the appdir obtained from mise's own resolution (the `cask_appdir`/`target_app_dir` value) rather than an arbitrary directory
- Ensure the APP_DIR env override, if set, is a valid absolute path so it lands in `allowed_appdir_roots()`
- Rewrite the cask target to a prefix-anchored path (`$HOMEBREW_PREFIX/bin/...`) if it is not meant to live in the appdir
- Update the calling code so `$APPDIR` targets are only evaluated against allowed appdir roots
Example fix
// before (Rust caller)
binary_target_path("$APPDIR/bin/tool", &staging_dir)?
// after
let appdir = cask_appdir()?;
binary_target_path("$APPDIR/bin/tool", &appdir)? Defensive patterns
Strategy: validation
Validate before calling
fn appdir_allowed(appdir: &std::path::Path) -> bool {
appdir == std::path::Path::new("/Applications")
|| appdir == std::path::Path::new("/opt/homebrew/Applications")
|| appdir == std::path::Path::new("/usr/local/Applications")
} Try / catch
match result {
Err(e) if e.to_string().contains("invalid appdir") => {
eprintln!("pass an allowed appdir root for $APPDIR binary targets");
}
r => r?,
} Prevention
- Only evaluate $APPDIR/... targets against the appdir returned by mise's own resolution
- Do not pass staging or arbitrary directories as the appdir
- Keep any APP_DIR override valid and absolute so it joins the allowed roots
- Prefer $HOMEBREW_PREFIX targets when a binary is not meant for the appdir
When it happens
Trigger: Calling `binary_target_path(target, appdir)` (via `target_path` or `binary_targets_must_stay_under_an_allowed_root`) with a target starting `$APPDIR/` and an `appdir` argument not equal to any entry of `allowed_appdir_roots()` — e.g. a caller passing a staging path or a custom directory as appdir.
Common situations: Custom cask tooling passing its own directory as appdir; an APP_DIR override typo making the computed appdir mismatch the allowed roots; stale code assuming any directory works with `$APPDIR` targets.
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
- brew-cask: refusing generic artifact copy outside Homebrew p
- brew-cask: invalid generic artifact parent
- brew-cask: generic artifact target '{}' must stay below {}
- brew-cask: invalid font target '{}'
- brew-cask: invalid structured flight path '{}'
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/75f3d1f0f416bfea.
Report an issue: GitHub.