jdx/mise · info
declined; nothing was changed
Error message
declined; nothing was changed
What it means
`mise history` (rollback/undo/apply) refreshes its plan before writing anything, and if the refreshed plan still contains unresolved conflicts it asks for confirmation. This error is thrown when the user (or a non-interactive caller answering 'no') declines that confirmation. It is a deliberate no-op guard: nothing on disk was touched.
Solutions
- Re-run with `--yes` if you intend to apply the plan non-interactively.
- Inspect the printed plan first; resolve conflicts (e.g. revert or manually restore the conflicting paths) so the refreshed plan is conflict-free.
- Run the command interactively and answer `y` when the plan looks correct.
Example fix
// before mise history rollback // error: declined; nothing was changed // after mise history rollback --yes
Defensive patterns
Strategy: validation
Validate before calling
if !has_conflicts(plan) { run_rollback_with_yes(); } else { review_plan_and_resolve(plan); } Prevention
- Prefer `--yes` in scripts only after confirming the plan is conflict-free.
- Review the refreshed plan output before answering the confirmation.
- Resolve conflicting paths up front so no confirmation prompt appears.
When it happens
Trigger: Running `mise history rollback`/`undo`/`apply` without `--yes` when the refreshed plan contains Action::Conflict steps; `prompt::confirm` returned a non-yes answer inside apply_steps.
Common situations: Non-interactive CI/script runs where confirm() cannot get a yes; a user reviewing the refreshed plan and choosing not to proceed because live files differ from the original plan.
Related errors
- adoption requires confirmation; review the directory and…
- cannot set up from a setup repository
- invalid checkpoint reference
- no history checkpoint matches
- matches more than one checkpoint; use a longer prefix
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/233da9ab9e1baa1a.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/history/replay.rs:505
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![];
for step in steps.iter().filter(|step| step.action.mutates()) {
let Some(current) = repo.restored_object_at(&live, &step.tree_path)? else {
continue;View on GitHub (pinned to 533346cc37)