jdx/mise · error · eyre::Report
completion target is not an owned Caskroom symlink: {}
Error message
completion target is not an owned Caskroom symlink: {} What it means
Completion targets must be symlinks under a default completion directory for one of the supported shells (bash, fish, zsh, pwsh) and resolve into the cask's Caskroom version directory. The prune refuses to touch completion files that are real files, sit in custom completion dirs, or point elsewhere.
Source
Thrown at src/system/packages/brew/cask.rs:7106
}
let completion_roots = [
CompletionShell::Bash,
CompletionShell::Fish,
CompletionShell::Zsh,
CompletionShell::Pwsh,
]
.map(default_completion_dir);
for path in &receipt.completions {
let record = records
.get(path)
.ok_or_else(|| eyre!("missing completion target record"))?;
if record.fingerprint.kind != CaskTargetKind::Symlink
|| !completion_roots
.iter()
.any(|root| path_is_below(path, root))
|| !symlink_resolves_below(path, &candidate.version_dir)
{
bail!(
"completion target is not an owned Caskroom symlink: {}",
path.display()
);
}
}
for record in &receipt.targets {
if !cask_target_record_matches(record)? {
bail!("artifact target has changed: {}", record.path.display());
}
}
Ok(())
}
fn path_is_below(path: &Path, root: &Path) -> bool {
path.strip_prefix(root)
.is_ok_and(|relative| relative.components().next().is_some())
}
View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Recreate the completion as a symlink into Caskroom/<token>/<version>/ under the shell's default completion directory
- Reinstall the cask to regenerate completions and their receipt, then prune
- Remove manually-installed completion files yourself and uninstall the cask instead of pruning
Defensive patterns
Strategy: validation
Validate before calling
// Check completions are symlinks under a default completion dir pointing
// into the cask version dir.
fn completion_ok(path: &Path, version_dir: &Path) -> bool {
let roots = [CompletionShell::Bash, CompletionShell::Fish, CompletionShell::Zsh, CompletionShell::Pwsh]
.map(default_completion_dir);
path.symlink_metadata().map(|m| m.file_type().is_symlink()).unwrap_or(false)
&& roots.iter().any(|root| path_is_below(path, root))
&& symlink_resolves_below(path, version_dir)
} Type guard
fn is_default_dir_completion(path: &Path) -> bool {
[CompletionShell::Bash, CompletionShell::Fish, CompletionShell::Zsh, CompletionShell::Pwsh]
.map(default_completion_dir)
.iter()
.any(|root| path_is_below(path, root))
} Try / catch
// Skip the affected cask, keep pruning the rest; report which completion path failed.
if let Err(reason) = validate_cask_prune_candidate(candidate) {
warn!("brew-cask:{}: {reason:#}", candidate.token);
continue;
} Prevention
- Let the cask own its completion symlinks; don't let plugin managers overwrite them with copies
- If a framework replaces completions, reinstall the cask before pruning
When it happens
Trigger: validate_cask_prune_candidate, completions loop: fingerprint kind != Symlink, path not below any default_completion_dir(shell) root, or symlink_resolves_below(path, version_dir) false. Produced when shell completion files were copied over the links, a framework (e.g. a shell plugin manager) regenerated them, or completions were installed into a non-default directory.
Common situations: oh-my-zsh / Fisher / completions managers rewriting completion files; user copying the completion into a custom fpath dir; stale links after a Homebrew relink.
Related errors
- binary target is not an owned Caskroom symlink: {}
- artifact target has changed: {}
- ownership receipt has changed
- receipt is not marked safe for direct-artifact pruning
- receipt target inventory is incomplete or duplicated
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/1de2dd4889ae560e.
Report an issue: GitHub.