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

  1. Run undo again or pick a checkpoint that corresponds to an actual operation
  2. Use rollback with explicit paths instead of undo for non-operation checkpoints
  3. 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

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


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