jdx/mise · error

cannot link {name}: these files already exist and were not c

Error message

cannot link {name}: these files already exist and were not created by mise or brew:
{}
Remove or rename them, then re-run `mise bootstrap packages apply`

What it means

When linking a keg into the brew prefix, pour checks each target path; if a file or symlink already exists that was not created by mise or brew, it refuses to link and lists the conflicting paths. Nothing has been linked yet — the caller rolls the keg back — so the error lists files to remove and the exact command to re-run.

Source

Thrown at src/system/packages/brew/pour.rs:597

                let dest = prefix_path.join(rel);
                if !can_overwrite(&dest) {
                    conflicts.push(dest);
                } else {
                    links.push((dest, entry.path().to_path_buf()));
                }
            }
        }
        let linked = prefix::linked_keg_record(name);
        if can_overwrite(&linked) {
            links.push((linked, keg.clone()));
        } else {
            conflicts.push(linked);
        }
    }
    if !conflicts.is_empty() {
        // nothing has been linked yet, and the caller rolls the keg back on
        // this error — so don't claim it remains usable
        bail!(
            "cannot link {name}: these files already exist and were not created by mise or brew:\n{}\n\
             Remove or rename them, then re-run `mise bootstrap packages apply`",
            conflicts
                .iter()
                .map(|p| format!("  {}", p.display()))
                .collect::<Vec<_>>()
                .join("\n"),
        );
    }
    // remember every symlink we overwrite (upgrades replace the previous
    // version's links, opt included) so a failed link restores all of them
    let mut created: Vec<PathBuf> = vec![];
    let mut replaced: Vec<(PathBuf, PathBuf)> = vec![];
    let mut failure: Option<eyre::Report> = None;
    for (dest, target) in &links {
        let made = (|| -> Result<()> {
            // a parent that is a brew directory symlink must become a real
            // directory first — otherwise the link below would be created

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Remove or rename the listed conflicting files/symlinks yourself
  2. Re-run `mise bootstrap packages apply`
  3. If a conflicting symlink points into another Cellar keg, uninstall or relink that keg first
  4. Verify ownership before deleting system-wide files

Example fix

# before
ls -l /home/linuxbrew/.linuxbrew/bin/tool  # foreign symlink
rm /home/linuxbrew/.linuxbrew/bin/tool
# after
mise bootstrap packages apply
Defensive patterns

Strategy: validation

Validate before calling

const conflicts = kegPaths.filter(p => fs.existsSync(p) && !createdByMiseOrBrew(p));
if (conflicts.length) console.error('remove or rename:', conflicts);

Try / catch

catch (e) {
  if (String(e).startsWith('cannot link')) {
    const files = e.message.split('\n').filter(l => l.startsWith('  ')).map(l => l.trim());
    files.forEach(f => fs.renameSync(f, f + '.bak'));
    return retryApply();
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `mise bootstrap packages apply` on a machine where a manually installed copy of the tool (make install, a different package manager, hand-placed symlinks) already occupies files under the brew prefix that link_keg would create.

Common situations: Switching from manual source installs to brew bottles; leftovers from a previous tool manager that used different markers; a stale symlink pointing outside the Cellar; another keg owns a shared directory.

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/85fe2573bfc55570. Report an issue: GitHub.