jdx/mise · error

the refreshed plan has conflicts; nothing was changed

Error message

the refreshed plan has conflicts; nothing was changed

What it means

When `mise history` applies a replay plan, it re-plans against the live tree if the working tree changed since the plan was shown. If the refreshed plan contains any Action::Conflict steps, mise refuses to proceed so no user data is silently clobbered. This is a deliberate safety abort, not a bug.

Source

Thrown at src/system/history/replay.rs:502

) -> Result<Vec<PathBuf>> {
    let _ = (store, entries);
    let mut round = 0;
    let mut live;
    loop {
        round += 1;
        // editors may have written while the prompt was open: re-plan
        live = live_tree(repo, tracked)?;
        let fresh = plan(repo, exec, &live)?;
        let changed = actionable(&fresh) != actionable(steps);
        if changed {
            *steps = fresh.clone();
            miseprintln!("history: the working tree changed since the plan was shown:");
            print_plan(steps, exec, tracked)?;
            if steps
                .iter()
                .any(|step| matches!(step.action, Action::Conflict(_)))
            {
                bail!("the refreshed plan has conflicts; nothing was changed");
            }
            if !exec.yes && !prompt::confirm("history: apply the refreshed plan?")?.is_yes() {
                bail!("declined; nothing was changed");
            }
        }
        // completeness: every path about to be written or deleted that exists
        // now must be captured, as it is now, in the protective checkpoint
        let Some((before_id, _)) = scope.before() else {
            bail!("no protective checkpoint could be taken; nothing was changed");
        };
        let before = store::entry(store, before_id)?;
        let before_tree = before
            .checkpoint
            .tree
            .snapshot
            .clone()
            .ok_or_else(|| eyre::eyre!("the protective checkpoint has no content"))?;
        let mut missing = vec![];

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Commit or stash the concurrent working-tree changes, then re-run the replay so the refreshed plan is conflict-free
  2. Inspect the refreshed plan printed above the error and manually resolve the conflicting paths
  3. Re-run with the tree in a stable state (close editors/watchers) and apply again
Defensive patterns

Strategy: validation

Validate before calling

// before applying, ensure no conflicts exist in the refreshed plan
if steps.iter().any(|s| matches!(s.action, Action::Conflict(_))) {
    eprintln!("resolve conflicts before applying");
    return;
}

Prevention

When it happens

Trigger: Running `mise history` replay/apply without --yes after files were modified between plan display and confirmation, such that the re-computed plan detects a conflict (target path differs from both snapshot and what was shown).

Common situations: An editor, build tool, or another mise process writes files while the user is reviewing the plan prompt; applying an old plan to a tree that has since changed.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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