jdx/mise · error
brew-cask: app target '{target_name}' must be an absolute pa
Error message
brew-cask: app target '{target_name}' must be an absolute path What it means
When a cask `app target:` contains a `/` it must be an absolute path; relative multi-component targets are ambiguous and could escape containment, so `app_target_path` rejects them. Bare names without `/` (e.g. `Foo.app`) are fine and are joined to the app dir. This error fires for values like `Foo/Bar.app` without a leading slash.
Source
Thrown at src/system/packages/brew/cask/paths.rs:146
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> {
let Ok(dir) = crate::env::var(APP_DIR_ENV) else {
return Ok(PathBuf::from(DEFAULT_APP_DIR));
};
if dir.is_empty() {
return Ok(PathBuf::from(DEFAULT_APP_DIR));View on GitHub (pinned to afd2eddd3a)
Solutions
- Prefix the target with `/` (or the appropriate absolute root) so it is an absolute path, e.g. `/Applications/Subdir/Foo.app`
- Use a plain app-bundle name without `/` and let mise place it in the app dir: `Foo.app`
- Use `$HOMEBREW_PREFIX/...` or `$APPDIR/...` placeholders if the target is meant to be relative to those roots
Example fix
// before (cask stanza) app target: 'Utilities/Foo.app' // after app target: '/Applications/Utilities/Foo.app'
Defensive patterns
Strategy: validation
Validate before calling
fn app_target_is_absolute_or_bare(target: &str) -> bool {
!target.contains('\0') && (!target.contains('/') || target.starts_with('/') || target.starts_with("$HOMEBREW_PREFIX/") || target.starts_with("$APPDIR/"))
} Try / catch
match result {
Err(e) if e.to_string().contains("must be an absolute path") => {
eprintln!("add a leading '/' or drop the '/' to use a bare bundle name");
}
r => r?,
} Prevention
- Multi-component app targets must start with `/`
- If you only need the bundle placed in the app dir, omit all slashes
- Check placeholder spellings ($HOMEBREW_PREFIX/, $APPDIR/) include the trailing slash
- Lint custom casks for relative nested targets
When it happens
Trigger: Calling install/validation via `app_target_path` with a target string containing `/` but not starting with `/`, `$HOMEBREW_PREFIX/`, or `$APPDIR/` — e.g. `target: 'Subdir/Foo.app'`.
Common situations: Typo dropping the leading slash from an absolute target; hand-written custom cask with a nested relative target; misuse of `$HOMEBREW_PREFIX` placeholder spelling.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 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/b067796926e01f52.
Report an issue: GitHub.