{"record":{"id":"b067796926e01f52","repo":"jdx/mise","slug":"brew-cask-app-target-target-name-must-be-an-a-b06779","errorCode":null,"errorMessage":"brew-cask: app target '{target_name}' must be an absolute path","messagePattern":"brew-cask: app target '(.+?)' must be an absolute path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/paths.rs","lineNumber":146,"sourceCode":"            if path.starts_with(&app_dir) || path.starts_with(&prefix_app_dir) {\n                return Ok(path);\n            }\n            // Casks routinely hardcode an absolute `/Applications/Foo.app`\n            // target. When an override appdir is configured, relocate such a\n            // target into it (preserving any subdirectories) rather than\n            // rejecting it. `$HOMEBREW_PREFIX`-anchored targets are handled by\n            // the check above and are never relocated.\n            if app_dir != Path::new(DEFAULT_APP_DIR)\n                && let Ok(rest) = path.strip_prefix(DEFAULT_APP_DIR)\n            {\n                return Ok(app_dir.join(rest));\n            }\n            bail!(\n                \"brew-cask: app target '{target_name}' must be under {}\",\n                app_dir.display()\n            );\n        }\n        bail!(\"brew-cask: app target '{target_name}' must be an absolute path\");\n    }\n    Ok(app_dir.join(target_name))\n}\n\n/// The directory `app` artifacts are linked into: `/Applications` unless\n/// [`APP_DIR_ENV`] overrides it.\n///\n/// The override is validated here rather than at the point of use because\n/// `app_target_path` treats the result as a containment boundary for symlinks\n/// that may be created with elevated privileges. An empty value falls back to\n/// the default so that exporting `MISE_BREW_CASK_OPT_APPDIR=` cannot disable\n/// that boundary: `Path::starts_with(\"\")` is true for every path.\npub(super) fn target_app_dir() -> Result<PathBuf> {\n    let Ok(dir) = crate::env::var(APP_DIR_ENV) else {\n        return Ok(PathBuf::from(DEFAULT_APP_DIR));\n    };\n    if dir.is_empty() {\n        return Ok(PathBuf::from(DEFAULT_APP_DIR));","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/paths.rs#L128-L164","documentation":"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.","triggerScenarios":"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'`.","commonSituations":"Typo dropping the leading slash from an absolute target; hand-written custom cask with a nested relative target; misuse of `$HOMEBREW_PREFIX` placeholder spelling.","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"],"exampleFix":"// before (cask stanza)\napp target: 'Utilities/Foo.app'\n// after\napp target: '/Applications/Utilities/Foo.app'","handlingStrategy":"validation","validationCode":"fn app_target_is_absolute_or_bare(target: &str) -> bool {\n    !target.contains('\\0') && (!target.contains('/') || target.starts_with('/') || target.starts_with(\"$HOMEBREW_PREFIX/\") || target.starts_with(\"$APPDIR/\"))\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"must be an absolute path\") => {\n        eprintln!(\"add a leading '/' or drop the '/' to use a bare bundle name\");\n    }\n    r => r?,\n}","preventionTips":["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"],"tags":["path-validation","brew-cask","invalid-argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}