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

When linking a completion artifact, mise refuses to overwrite an existing completion path unless it is a symlink (i.e., previously managed by mise or pointing into the cask). If a real file or directory already occupies the target, this error is thrown to avoid clobbering data mise does not own, identified by the cask token.

Source

Thrown at src/system/packages/brew/cask/mod.rs:2688

    }
    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 afd2eddd3a)

Solutions

  1. Inspect the existing file at the target path and back it up if you want to keep it
  2. Remove or rename the conflicting file/directory and re-run the install
  3. Verify the existing completion isn't owned by another tool (e.g. a system package) before deleting
  4. If another tool owns it, configure mise/the cask to use a different completion target

Example fix

// before: real file blocks the link
mv ~/.zsh/completions/_mytool ~/.zsh/completions/_mytool.bak
// after: install creates a mise-owned symlink
mise install <cask>
Defensive patterns

Strategy: try-catch

Validate before calling

p=<target-path>; if [ -e "$p" ] && [ ! -L "$p" ]; then echo "non-symlink exists at $p — will conflict"; fi

Try / catch

match result {
  Err(e) if e.contains("already exists and is not owned by cask") => {
    eprintln!("back up and remove the existing non-symlink at the target, then reinstall: {e}");
  }
  Err(e) => return Err(e),
  Ok(v) => v,
}

Prevention

When it happens

Trigger: `target.symlink_metadata()` succeeds and `!metadata.file_type().is_symlink()` — a regular file, directory, or other non-symlink already exists at the completion target path before this cask is linked.

Common situations: The user (or Homebrew previously) installed a real completion file at the same path; another package manager owns the completion; a previous non-symlink install left files behind.

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


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/3b9b440507288c03. Report an issue: GitHub.