jdx/mise · error

{} differs from its managed source; use --force to remove it

Error message

{} differs from its managed source; use --force to remove it

What it means

In plan_expected_content (src/system/files.rs:2667), mise removes a target without --force only when the target is a regular, non-symlink file whose content byte-matches the managed source content. Any divergence (or a symlinked target) requires an explicit --force, preventing silent deletion of user-modified files.

Source

Thrown at src/system/files.rs:2667

    } else {
        bail!(
            "cannot verify {}; use --force to remove it",
            target.display_user()
        )
    }
}

fn plan_expected_content(
    expected: &[u8],
    target: &Path,
    force: bool,
    paths: &mut IndexMap<PathBuf, ()>,
) -> Result<()> {
    if force || (target.is_file() && !target.is_symlink() && file::read(target)? == expected) {
        paths.insert(target.to_path_buf(), ());
        Ok(())
    } else {
        bail!(
            "{} differs from its managed source; use --force to remove it",
            target.display_user()
        )
    }
}

/// All symlinks under a symlink-each target that point exactly where this
/// entry maps that relative path. Unlike stale-link pruning this includes
/// both current and deleted source files because unapply removes the entry's
/// complete observable footprint.
fn legacy_owned_links(req: &FileRequest) -> Result<Vec<PathBuf>> {
    if !req.target.is_dir() || req.target.is_symlink() {
        return Ok(vec![]);
    }
    let mut out = vec![];
    for entry in walkdir::WalkDir::new(&req.target).sort_by_file_name() {
        let entry = match entry {
            Ok(entry) => entry,

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Rerun unapply with --force once you've backed up the modified target
  2. Diff the target against the managed source to review local changes before forcing
  3. Re-copy the managed source over the target to restore exact content, then unapply without --force
  4. Update the source content in the dotfiles store to include the local changes

Example fix

# before
mise bootstrap dotfiles unapply
# error: ~/.zshrc differs from its managed source; use --force to remove it

# after
diff ~/.config/mise/dotfiles/zshrc ~/.zshrc  # review
cp ~/.zshrc ~/zshrc.local-changes.bak
mise bootstrap dotfiles unapply --force
Defensive patterns

Strategy: validation

Validate before calling

const expected = fs.readFileSync(entry.source);
const actual = fs.readFileSync(entry.target);
if (!actual.equals(expected)) {
  console.warn(`${entry.target} differs from managed source; unapply will need --force`);
}

Type guard

function contentMatches(source, target) {
  try { return fs.readFileSync(target).equals(fs.readFileSync(source)); }
  catch { return false; }
}

Try / catch

try {
  await unapply(plan);
} catch (e) {
  if (String(e).includes('differs from its managed source')) {
    backup(entry.target);
    await unapply({ ...plan, force: true });
  } else throw e;
}

Prevention

When it happens

Trigger: `mise bootstrap dotfiles unapply` (or plan_regular_file via it) where the target file's content differs from the expected bytes read from the source, or the target is a symlink, and opts.force is false.

Common situations: User edited the applied dotfile (e.g. customized .zshrc); a package manager or another sync tool rewrote the file; the source was updated after apply so contents no longer match.

Related errors


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