jdx/mise · error
brew-cask: completion target
Error message
brew-cask: completion target '{}' must be under {} What it means
This error enforces the containment part of the same path-safety check: after resolving the completion target (absolute, prefix-joined, or default-dir joined), the path must remain under the Homebrew prefix. If it starts outside the prefix (e.g. /etc/..., /Users/..., or an absolute path into another tree), the install is rejected to prevent casks from writing outside the managed prefix.
Solutions
- Change the target to use the $HOMEBREW_PREFIX placeholder instead of a hard-coded absolute path.
- Verify the Homebrew prefix on this machine (brew --prefix) and make the target relative or prefix-based so it resolves under it.
- If the file must live outside the prefix, install it out-of-band rather than through the cask completion mechanism.
- Update a stale cask recipe that assumes the /usr/local prefix to the prefix-independent form.
Example fix
// before (Intel-style absolute path on Apple Silicon)
completions = [{ target = "/usr/local/etc/bash_completion.d/mytool" }]
// after
completions = [{ target = "$HOMEBREW_PREFIX/etc/bash_completion.d/mytool" }] Defensive patterns
Strategy: validation
Validate before calling
let target = resolve_target(target_name)?; // apply $HOMEBREW_PREFIX substitution first
if !target.starts_with(&prefix) {
return Err(format!("target {} is outside prefix {}", target.display(), prefix.display()));
} Prevention
- Always express custom completion locations via $HOMEBREW_PREFIX instead of hard-coded absolute paths.
- Check `brew --prefix` per machine; do not assume /usr/local vs /opt/homebrew.
- Test cask recipes on both Intel and Apple Silicon prefix layouts before distributing.
When it happens
Trigger: A cask completion target declared as an absolute path outside the Homebrew prefix (e.g. /etc/bash_completion.d/foo or /usr/local/share/... when the prefix is /opt/homebrew), or an absolute target that does not begin with the current prefix after $HOMEBREW_PREFIX substitution.
Common situations: A cask written for an Intel Homebrew layout (/usr/local) being installed on Apple Silicon (/opt/homebrew); hard-coded absolute paths in a hand-rolled cask; a $HOMEBREW_PREFIX substitution producing a non-prefix root; shared cask recipes copied between systems with different prefixes.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- brew-cask: completion target
- brew-cask: completion target
- brew-cask: app target
- brew-cask: binary target
- brew-cask: generic artifact source is not contained by the…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/a768c3cf2c2c3fc0.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/mod.rs:3178
let path = PathBuf::from(&target_name);
let target = if path.is_absolute() {
path
} else if target_name.contains('/') {
prefix.join(path)
} else {
default_completion_dir(shell).join(completion_filename(shell, &target_name)?)
};
if target
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!(
"brew-cask: completion target '{}' must not contain '..'",
target.display()
);
}
if !target.starts_with(&prefix) {
bail!(
"brew-cask: completion target '{}' must be under {}",
target.display(),
prefix.display()
);
}
Ok(target)
}
fn generated_completion_target_path(shell: CompletionShell, base_name: &str) -> Result<PathBuf> {
match shell {
CompletionShell::Pwsh => {
let name = format!("_{}.ps1", base_name);
completion_target_path(shell, &name)
}
_ => completion_target_path(shell, base_name),
}
}
View on GitHub (pinned to 533346cc37)