jdx/mise · error
no protective checkpoint could be taken; nothing was changed
Error message
no protective checkpoint could be taken; nothing was changed
What it means
Before applying any step, apply_steps takes a protective checkpoint of the current state of every path the plan will write or delete. If that checkpoint could not be taken (scope.before() returned None), mise aborts with this error rather than mutating files it could not protect. Nothing was changed.
Solutions
- Check the history store directory is writable and not corrupted; run `mise history` listing to verify entries are being recorded.
- Retry the rollback/undo command; transient capture failures often clear on retry.
- Inspect `MISE_DEBUG=1` output for why the checkpoint capture returned nothing before forcing any manual restore.
Defensive patterns
Strategy: retry
Validate before calling
test -w "$(mise history dir 2>/dev/null || echo ~/.local/share/mise/history)" && echo writable
Try / catch
match result { Err(msg) if msg.contains("no protective checkpoint") => { fix_store(); retry(); }, other => other } Prevention
- Keep the history store writable by the user running mise.
- Verify checkpoints appear in `mise history` during normal work.
- Avoid killing mise mid-operation, which can leave unusable scopes.
When it happens
Trigger: scope.before() is None in apply_steps — the snapshot/checkpoint capture produced no entry id for the current scope, e.g. the history store or capture walk failed to record a usable 'before' state.
Common situations: Corrupt or unwritable history store; live tree capture failing for the target paths; unusual filesystem states that make snapshot capture return no checkpoint.
Related errors
- changed after it was protected; nothing more was changed
- checkpoint has no content snapshot
- appeared after was protected; nothing more was changed
- cannot protect
- cannot retain an unreadable plaintext version of newly…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/dd99dd206db4758d.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/history/replay.rs:511
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;
};
if repo.restored_object_at(&before_tree, &step.tree_path)? != Some(current) {
missing.push(step.path.clone());
}
}
if missing.is_empty() {View on GitHub (pinned to 533346cc37)