jdx/mise · error
brew-cask: completion target '{}' already exists and is not
Error message
brew-cask: completion target '{}' already exists and is not owned by cask '{}' What it means
The completion link target already exists and is not a symlink (a regular file or directory). A completion target may only be replaced when it is a symlink whose ownership this cask can prove; a foreign real file is never clobbered, so the install aborts with the cask token in the message.
Source
Thrown at src/system/packages/brew/cask.rs:4146
}
if let Some(parent) = target.parent() {
create_dir_all_elevating(parent)?;
}
ensure_completion_target_replaceable(cask, artifacts, target)?;
make_symlink_elevating(&caskroom_completion, target)?;
Ok(())
}
fn ensure_completion_target_replaceable(
cask: &Cask,
artifacts: &CaskArtifacts,
target: &Path,
) -> Result<()> {
let Ok(metadata) = target.symlink_metadata() else {
return Ok(());
};
if !metadata.file_type().is_symlink() {
bail!(
"brew-cask: completion target '{}' already exists and is not owned by cask '{}'",
target.display(),
cask.token
);
}
let link_target = std::fs::read_link(target)?;
let resolved = resolve_symlink_target(target, link_target);
let token_dir = caskroom_token_dir(&cask.token);
if path_starts_with_resolved_root(&resolved, &token_dir) {
return Ok(());
}
for completion in &artifacts.completions {
if completion.target_path()? != target {
continue;
}
if let Some(source) = appdir_artifact_source(&completion.source, &artifacts.apps)?
&& file::same_file(&resolved, &source)
{View on GitHub (pinned to 6f52dcdf99)
Solutions
- Delete or rename the non-symlink file at the completion target after confirming it is not needed
- Change the completion artifact's target to a cask-unique file name
- Adjust user setup scripts to symlink rather than copy completions so ownership checks pass
Example fix
# shell - resolve the foreign regular file before reinstalling ls -l ~/.zsh/completions/_myapp # regular file, not a symlink mv ~/.zsh/completions/_myapp ~/.zsh/completions/_myapp.bak
Defensive patterns
Strategy: validation
Validate before calling
// Only proceed when the completion target is absent or a symlink we may own
match target.symlink_metadata() {
Err(_) => Ok(()),
Ok(m) if m.file_type().is_symlink() => Ok(()),
Ok(_) => Err(eyre!("completion target '{}' is a real file/dir; move it aside first", target.display())),
} Try / catch
if err.to_string().contains("completion target") && err.to_string().contains("is not owned by cask") {
// surface the path and the cask token so the user can relocate the foreign file
} Prevention
- Never copy completion files into shared completion directories; symlink them
- Check the target path with ls -l before installing a cask that links completions
- Namespace completion target names by tool to avoid collisions
When it happens
Trigger: A user dotfiles setup or another package copied a real completion file to the target path; the target path exists as a directory rather than a link.
Common situations: Dotfiles repositories that `cp` completions into place; a distro or other package manager installing the same completion name; README instructions telling users to copy the completion file manually.
Related errors
- brew-cask:{}: Homebrew owns this cask; remove it with Homebr
- brew-cask: completion target '{}' already points to '{}' and
- brew-cask:{}: conflicts with installed cask {}
- brew-cask: cannot adopt '{}': existing artifact is not ident
- brew-cask: staging directory is not owned by the current use
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/9a5033eacdee72f7.
Report an issue: GitHub.