jdx/mise · error
brew-cask: completion target '{}' must be under {}
Error message
brew-cask: completion target '{}' must be under {} What it means
After rejecting `..` components, mise enforces that the resolved completion target still starts with the expected prefix (the shell's default completion directory). This is a second containment check: even without traversal components, a target that resolves outside the managed tree (e.g. via absolute construction or prefix mismatch) is rejected to keep cask completions inside mise's completion directories.
Source
Thrown at src/system/packages/brew/cask/mod.rs:2961
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 afd2eddd3a)
Solutions
- Make the cask's completion target relative so it lands under the shell's default completion directory
- Check your HOME/completion-dir environment so the resolved prefix matches expectations
- If you need completions elsewhere, link them yourself manually after install rather than via the cask stanza
Example fix
// before (cask stanza) completion "/usr/local/share/fish/vendor_completions.d/x.fish" // after completion "x.fish" # goes under the managed fish completions dir
Defensive patterns
Strategy: validation
Validate before calling
let prefix = std::path::Path::new("<expected-completion-dir>");
assert!(target_path.starts_with(prefix), "completion target must stay under the shell's completion dir"); Type guard
fn stays_under(prefix: &std::path::Path, target: &std::path::Path) -> bool {
target.starts_with(prefix)
} Try / catch
if let Err(e) = result {
if e.contains("must be under") {
eprintln!("completion target escaped the managed tree; make it relative so it lands under the default completion dir");
}
} Prevention
- Keep completion targets relative to the shell's default directory
- Avoid overriding the completion directory to outside locations
- Check HOME-dependent path resolution when installs run in different environments
When it happens
Trigger: `!target.starts_with(&prefix)` where `prefix` is the expected completion directory for the shell — the computed target (e.g. `default_completion_dir(shell).join(...)`) resolved to a path not under that prefix.
Common situations: A cask overrides the completion directory to somewhere outside mise's managed tree; an environment/`HOME` mismatch makes the resolved target diverge from the expected prefix; a custom completion target on a different filesystem or volume-style path.
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 '{}' must not contain '..'
- brew-cask: completion target '{}' must not contain '..'
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/a768c3cf2c2c3fc0.
Report an issue: GitHub.