{"record":{"id":"46d9b5098cb90dff","repo":"jdx/mise","slug":"brew-cask-completion-target-already-points-t-46d9b5","errorCode":null,"errorMessage":"brew-cask: completion target '{}' already points to '{}' and is not owned by cask '{}'","messagePattern":"brew-cask: completion target '(.+?)' already points to '(.+?)' and is not owned by cask '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/mod.rs","lineNumber":2927,"sourceCode":"        );\n    }\n    let link_target = std::fs::read_link(target)?;\n    let resolved = resolve_symlink_target(target, link_target);\n    let token_dir = caskroom_token_dir(&cask.token);\n    if path_starts_with_resolved_root(&resolved, &token_dir) {\n        return Ok(());\n    }\n    for completion in &artifacts.completions {\n        if completion.target_path()? != target {\n            continue;\n        }\n        if let Some(source) = appdir_artifact_source(&completion.source, &artifacts.apps)?\n            && file::same_file(&resolved, &source)\n        {\n            return Ok(());\n        }\n    }\n    bail!(\n        \"brew-cask: completion target '{}' already points to '{}' and is not owned by cask '{}'\",\n        target.display(),\n        resolved.display(),\n        cask.token\n    )\n}\n\nfn find_completion_source(\n    stage: &Path,\n    caskroom: &Path,\n    cask: &Cask,\n    apps: &[AppArtifact],\n    source: &str,\n) -> Result<Option<PathBuf>> {\n    for root in [caskroom, stage] {\n        if let Some(source) = generated_caskroom_artifact(root, cask, source)\n            && source.is_file()\n        {","sourceCodeStart":2909,"sourceCodeEnd":2945,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/mod.rs#L2909-L2945","documentation":"For an existing symlink at a cask completion target, mise resolves it and checks ownership: the link must point at the staged caskroom artifact (or, for appdir artifacts, a file identical to the matching staged app source). If the resolved link points elsewhere, the target is owned by another installation (or a stale link), so mise bails instead of repointing a link it doesn't own.","triggerScenarios":"Installing a cask whose completion target already is a symlink, but read_link/resolution shows it points to a path that is not this cask's staged artifact, and it is not same_file to the matching appdir artifact source for cask.token.","commonSituations":"A symlink created by native Homebrew or another version manager points at its own Cellar/Caskroom; a stale symlink survives after the old cask version was deleted; two casks or tools claim the same binary name (e.g. two CLI tools installing the same shim path).","solutions":["Remove the foreign/stale symlink at the target path and retry the cask install.","Identify what created the link (brew cask, other tool) and uninstall that owner first.","If the link points at a deleted old version, it is stale — delete it and reinstall.","If two tools legitimately conflict, choose one or adjust the completion target in configuration."],"exampleFix":"// before: symlink owned by another install\nreadlink /usr/local/bin/mytool  # /opt/homebrew/Caskroom/other/1.0/bin/mytool\n\n// after: remove the foreign link and reinstall\nrm /usr/local/bin/mytool && mise install cask://my-tool","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn link_owned_by_cask(target: &Path, caskroom_prefix: &str) -> bool {\n    target\n        .read_link()\n        .ok()\n        .map(|l| l.to_string_lossy().contains(caskroom_prefix))\n        .unwrap_or(false)\n}","typeGuard":"fn is_symlink(target: &std::path::Path) -> bool {\n    target\n        .symlink_metadata()\n        .map(|md| md.file_type().is_symlink())\n        .unwrap_or(false)\n}","tryCatchPattern":"// Rust\nmatch install_cask_completion(&cask, &artifacts, &caskroom, &target) {\n    Err(e) if e.to_string().contains(\"already points to\") => {\n        // inspect readlink(target); remove stale/foreign link, then retry once\n    }\n    other => other,\n}","preventionTips":["Keep symlink ownership per package: never share one bin path across brew cask and mise cask.","Clean up symlinks after uninstalling the previous manager for a tool.","Watch for stale links to deleted cask versions and remove them.","Resolve existing links with readlink before installing to detect conflicts early."],"tags":["brew-cask","symlink-ownership","conflict","link-target"],"backgroundTag":"file-already-exists","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}