jdx/mise · error

brew-cask: app target

Error message

brew-cask: app target '{target_name}' must be under {}

What it means

For relative-sounding or absolute app targets that escaped the earlier checks, `app_target_path` requires the final path to live under the configured app directory. An absolute path not starting with the app dir or prefix Applications dir (and not relocatable from DEFAULT_APP_DIR) is rejected; a path that is not absolute at all is rejected with the sibling 'must be an absolute path' error.

Solutions

  1. Change the app target to be under the configured app dir (default `/Applications` or `$HOMEBREW_PREFIX/Applications`).
  2. Set the cask app dir configuration to include the intended parent directory, then re-run install.
  3. Move the app into an allowed root and target it there if it must live elsewhere.

Example fix

# before
app target: "/Users/alice/Tools/MyApp.app"

# after
app target: "$HOMEBREW_PREFIX/Applications/MyApp.app"
Defensive patterns

Strategy: validation

Validate before calling

let app_dir = target_app_dir()?;
let p = std::path::PathBuf::from(expand(target_name));
if p.is_absolute() && !p.starts_with(&app_dir) {
    return Err(format!("target must be under {}", app_dir.display()));
}

Type guard

fn under_app_dir(p: &std::path::Path, app_dir: &std::path::Path) -> bool {
    p.is_absolute() && p.starts_with(app_dir)
}

Prevention

When it happens

Trigger: Passing an app target that is absolute but outside `$HOMEBREW_PREFIX/Applications`, the configured app_dir, or DEFAULT_APP_DIR (e.g. `/Users/me/Tools/Foo.app` or `/opt/Foo.app`) through any app install/adopt/validate call site.

Common situations: Pointing a cask app at a personal directory instead of the Homebrew Applications folder; switching the configured app_dir so previously valid targets now fall outside it; a cask definition hardcoding a non-standard absolute location.

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/2e47dddb532f173c. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/brew/cask/paths.rs:141

        {
            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.
pub(super) fn target_app_dir() -> Result<PathBuf> {

View on GitHub (pinned to 533346cc37)