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

  1. 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
  2. Edit the cask's target to a bare bundle name ("Foo.app") or an absolute /Applications/... path
  3. Install that cask with `brew install --cask <token>` directly — Homebrew may permit target locations mise deliberately refuses
  4. 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

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


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/a245685b206cbd0c. Report an issue: GitHub.