{"record":{"id":"914618bd1ec1bd6a","repo":"jdx/mise","slug":"the-refreshed-plan-has-conflicts-nothing-was-chan","errorCode":null,"errorMessage":"the refreshed plan has conflicts; nothing was changed","messagePattern":"the refreshed plan has conflicts; nothing was changed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/replay.rs","lineNumber":502,"sourceCode":") -> Result<Vec<PathBuf>> {\n    let _ = (store, entries);\n    let mut round = 0;\n    let mut live;\n    loop {\n        round += 1;\n        // editors may have written while the prompt was open: re-plan\n        live = live_tree(repo, tracked)?;\n        let fresh = plan(repo, exec, &live)?;\n        let changed = actionable(&fresh) != actionable(steps);\n        if changed {\n            *steps = fresh.clone();\n            miseprintln!(\"history: the working tree changed since the plan was shown:\");\n            print_plan(steps, exec, tracked)?;\n            if steps\n                .iter()\n                .any(|step| matches!(step.action, Action::Conflict(_)))\n            {\n                bail!(\"the refreshed plan has conflicts; nothing was changed\");\n            }\n            if !exec.yes && !prompt::confirm(\"history: apply the refreshed plan?\")?.is_yes() {\n                bail!(\"declined; nothing was changed\");\n            }\n        }\n        // completeness: every path about to be written or deleted that exists\n        // now must be captured, as it is now, in the protective checkpoint\n        let Some((before_id, _)) = scope.before() else {\n            bail!(\"no protective checkpoint could be taken; nothing was changed\");\n        };\n        let before = store::entry(store, before_id)?;\n        let before_tree = before\n            .checkpoint\n            .tree\n            .snapshot\n            .clone()\n            .ok_or_else(|| eyre::eyre!(\"the protective checkpoint has no content\"))?;\n        let mut missing = vec![];","sourceCodeStart":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/replay.rs#L484-L520","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Commit or stash the concurrent working-tree changes, then re-run the replay so the refreshed plan is conflict-free","Inspect the refreshed plan printed above the error and manually resolve the conflicting paths","Re-run with the tree in a stable state (close editors/watchers) and apply again"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before applying, ensure no conflicts exist in the refreshed plan\nif steps.iter().any(|s| matches!(s.action, Action::Conflict(_))) {\n    eprintln!(\"resolve conflicts before applying\");\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the working tree quiet (no watchers/builds) while reviewing history plans","Apply plans promptly instead of leaving them open for confirmation","Use --yes only when the tree is known stable"],"tags":["history","replay","conflict","safety-abort"],"backgroundTag":"invalid-state-transition","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}