jdx/mise · error
brew-cask: completion target
Error message
brew-cask: completion target '{}' already exists and is not owned by cask '{}' What it means
When linking a cask completion artifact, mise refuses to overwrite an existing target that is not a symlink. If the destination path already exists as a regular file, directory, or other non-symlink, it cannot have been created by this cask, so bail! protects the pre-existing file from being clobbered, naming the cask token that wanted the target.
Solutions
- Back up and remove/rename the existing non-symlink file at the target path, then retry the install.
- Confirm the existing file is not needed: if it belongs to another package, remove that package instead.
- If the path should be a cask-owned symlink, delete the stale file/directory manually and reinstall the cask.
- Check whether an old install method (native brew cask) left the artifact and clean it up.
Example fix
// before: real file blocks the cask symlink ls -l /usr/local/bin/mytool # -rwxr-xr-x regular file // after: move it aside and reinstall mv /usr/local/bin/mytool /usr/local/bin/mytool.bak && mise install cask://my-tool
Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn link_target_free_or_symlink(target: &Path) -> bool {
match target.symlink_metadata() {
Ok(md) => md.file_type().is_symlink(),
Err(_) => true, // does not exist: safe
}
} Type guard
fn is_symlink_target(target: &std::path::Path) -> bool {
target
.symlink_metadata()
.map(|md| md.file_type().is_symlink())
.unwrap_or(false)
} Try / catch
// Rust
if let Err(e) = install_cask_completion(&cask, &artifacts, &caskroom, &target) {
if e.to_string().contains("already exists and is not owned") {
// prompt: back up & remove the existing file, then retry
} else {
return Err(e);
}
} Prevention
- Before installing casks, scan completion target dirs for pre-existing regular files.
- Avoid letting multiple package managers own the same bin paths.
- Use one installation method per binary target.
- Back up any file you remove from a completion target directory.
When it happens
Trigger: Installing a cask whose completion target path already exists on disk as a non-symlink (regular file or directory) — symlink_metadata() succeeds and file_type().is_symlink() is false.
Common situations: The user or another package manager previously placed a real file/directory at the target (e.g. /usr/local/bin/tool); a previous install created a directory where the cask wants a symlink; switching tools (e.g. from real brew to mise-managed casks) with leftovers in place.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- brew-cask: structured symlink target
- brew-cask: structured symlink target
- brew-cask: binary artifact
- brew-cask: cannot adopt
- brew-cask: completion target
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/3b9b440507288c03.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/mod.rs:2905
}
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 533346cc37)