jdx/mise · error · eyre::Report
brew-cask: app target '{target_name}' must be under {}
Error message
brew-cask: app target '{target_name}' must be under {} What it means
For absolute app targets, mise only allows paths under the effective app dir (default /Applications, overridable via MISE_BREW_CASK_OPT_APPDIR) or under <HOMEBREW_PREFIX>/Applications. When a custom appdir is configured, hardcoded /Applications/... targets are relocated into it via strip_prefix; this bail is what remains for absolute targets that point somewhere else entirely. It is the outer boundary of the app-target containment logic.
Source
Thrown at src/system/packages/brew/cask.rs:6006
{
bail!("brew-cask: app target '{target_name}' must not contain '..'");
}
if path.is_absolute() {
let prefix_app_dir = prefix::prefix().join("Applications");
if path.starts_with(&app_dir) || path.starts_with(&prefix_app_dir) {
return Ok(path);
}
// Casks routinely hardcode an absolute `/Applications/Foo.app`
// target. When an override appdir is configured, relocate such a
// target into it (preserving any subdirectories) rather than
// rejecting it. `$HOMEBREW_PREFIX`-anchored targets are handled by
// the check above and are never relocated.
if app_dir != Path::new(DEFAULT_APP_DIR)
&& let Ok(rest) = path.strip_prefix(DEFAULT_APP_DIR)
{
return Ok(app_dir.join(rest));
}
bail!(
"brew-cask: app target '{target_name}' must be under {}",
app_dir.display()
);
}
bail!("brew-cask: app target '{target_name}' must be an absolute path");
}
Ok(app_dir.join(target_name))
}
/// The directory `app` artifacts are linked into: `/Applications` unless
/// [`APP_DIR_ENV`] overrides it.
///
/// The override is validated here rather than at the point of use because
/// `app_target_path` treats the result as a containment boundary for symlinks
/// that may be created with elevated privileges. An empty value falls back to
/// the default so that exporting `MISE_BREW_CASK_OPT_APPDIR=` cannot disable
/// that boundary: `Path::starts_with("")` is true for every path.
fn target_app_dir() -> Result<PathBuf> {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- If you set MISE_BREW_CASK_OPT_APPDIR, unset it (or point it at the dir the cask actually targets) so the default /Applications containment applies
- Edit the cask's target to a bare bundle name ("Foo.app") or an absolute /Applications/... path
- Install that cask with `brew install --cask <token>` directly — Homebrew may permit target locations mise deliberately refuses
- Update mise in case newer builds widened the allowed roots
Example fix
# before export MISE_BREW_CASK_OPT_APPDIR=/opt/MyApps # cask target: "/Users/Shared/Foo.app" -> rejected # after: unset the override so /Applications containment applies unset MISE_BREW_CASK_OPT_APPDIR
Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn app_target_allowed(name: &str, app_dir: &Path, prefix_apps: &Path) -> bool {
if !name.contains('/') {
return true;
}
let expanded = name.replace("$HOMEBREW_PREFIX", "/opt/homebrew"); // your prefix
let p = Path::new(&expanded);
p.is_absolute() && (p.starts_with(app_dir) || p.starts_with(prefix_apps) || p.starts_with("/Applications"))
} Try / catch
match app_target_path(name) {
Ok(p) => p,
Err(e) if e.to_string().contains("must be under") => {
warn!("cask wants target outside app dir: {name}");
continue;
}
Err(e) => Err(e),
} Prevention
- Keep MISE_BREW_CASK_OPT_APPDIR unset unless you specifically need relocated /Applications targets
- Prefer bare bundle-name targets in custom casks so the app dir is chosen by mise
- Remember hardcoded absolute targets outside /Applications and <prefix>/Applications are rejected by design
When it happens
Trigger: A cask declaring an absolute target like "/Users/Shared/Foo.app" or "/Library/Application Support/Foo.app" that is under neither the app dir nor <prefix>/Applications; or a custom appdir where the target is absolute but not /Applications-anchored, so the relocation branch does not apply.
Common situations: Casks that install into non-standard locations; users setting MISE_BREW_CASK_OPT_APPDIR and hitting casks with targets outside /Applications; system-extended casks from third-party taps.
Related errors
- brew-cask: {APP_DIR_ENV} '{}' must not resolve to the filesy
- brew-cask is not available: {}
- brew-cask:{}: unsupported {kind} {field} base
- brew-cask: {APP_DIR_ENV} '{}' must be an absolute path
- brew-cask: {APP_DIR_ENV} '{}' must not contain '..'
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/a245685b206cbd0c.
Report an issue: GitHub.