jdx/mise · error
checkpoint {} is not an operation
Error message
checkpoint {} is not an operation What it means
Undo operates on checkpoints that record a dotfiles operation (with affected paths, status, and a protective before-checkpoint). The selected checkpoint exists but its checkpoint.operation field is None, meaning it is not an operation checkpoint, so there is nothing to undo. mise bails identifying the checkpoint by id.
Source
Thrown at src/system/history/replay.rs:272
undoes_of.insert(entry.checkpoint.uuid.clone(), target);
}
let operation = match &req.reference {
Some(reference) => crate::cli::dotfiles::history::resolve(reference, &entries, None)?,
None => entries
.iter()
.rev()
.find(|entry| {
entry.checkpoint.operation.as_ref().is_some_and(|op| {
op.status != OperationStatus::Pending
&& op.before.is_some()
&& !op.affected.is_empty()
}) && !undone.contains(&entry.checkpoint.uuid)
})
.cloned()
.ok_or_else(|| eyre::eyre!("nothing to undo: no tracked-file operation is left"))?,
};
let Some(op) = operation.checkpoint.operation.clone() else {
bail!("checkpoint {} is not an operation", operation.id);
};
// Undo restores tracked files only, never package or service state.
if op.status == OperationStatus::Pending {
bail!(
"checkpoint {} is still running or was interrupted; nothing to undo",
operation.id
);
}
if op.status == OperationStatus::Failed && !op.affected.is_empty() {
info!(
"history: operation {} failed midway; reversing the {} path(s) it changed",
operation.id,
op.affected.len()
);
}
let Some(before_uuid) = &op.before else {
bail!(
"checkpoint {} has no protective checkpoint to undo from",View on GitHub (pinned to afd2eddd3a)
Solutions
- Run undo again or pick a checkpoint that corresponds to an actual operation
- Use rollback with explicit paths instead of undo for non-operation checkpoints
- Inspect `mise bootstrap dotfiles history` to see which checkpoints are operations
Example fix
// before mise bootstrap dotfiles undo # targets a manual snapshot // after mise bootstrap dotfiles rollback --to <ref> --all # restore via rollback instead
Defensive patterns
Strategy: validation
Validate before calling
const entry = await getCheckpoint(id);
if (!entry?.checkpoint?.operation) {
throw new Error(`checkpoint ${id} is not an operation`);
} Type guard
const isOperation = (c: CheckpointEntry): c is CheckpointEntry & { checkpoint: { operation: Operation } } =>
c.checkpoint.operation != null; Try / catch
try {
await undo();
} catch (e) {
if (String(e).includes("is not an operation")) {
console.error("Use rollback for non-operation checkpoints.");
} else throw e;
} Prevention
- Check the history listing for operation checkpoints before undo
- Only construct undo requests from entries with a populated operation field
- Distinguish manual snapshots from operations in UI/tooling
When it happens
Trigger: Running `undo` when the most recent eligible checkpoint is a non-operation checkpoint (e.g. a manual snapshot/savepoint rather than a recorded operation). Condition: operation.checkpoint.operation.clone() is None.
Common situations: Users create manual checkpoints then try to undo them; history contains mixed checkpoint types after manual saves; undo picks an older checkpoint because newer ones were already undone.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- checkpoint {} is still running or was interrupted; nothing t
- checkpoint {} has no protective checkpoint to undo from
- checkpoint {} is unavailable; cannot find the state before o
- brew-cask: unresolved recovery for {} still preserves its or
- brew-cask: unresolved recovery for newly created target {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/01589bdeafd8ecf5.
Report an issue: GitHub.