jdx/mise · error

checkpoint {} is unavailable; cannot find the state before o

Error message

checkpoint {} is unavailable; cannot find the state before operation {}

What it means

Undo resolved the protective before-checkpoint UUID but cannot find a matching entry in the current history entries list — the checkpoint referenced by op.before is no longer available (pruned, removed, or the store was rebuilt). Since the restore source is gone, mise bails naming both the missing checkpoint and the operation that referenced it.

Source

Thrown at src/system/history/replay.rs:299

    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",
            operation.id
        );
    };
    let Some(before) = entries
        .iter()
        .find(|entry| &entry.checkpoint.uuid == before_uuid)
        .cloned()
    else {
        bail!(
            "checkpoint {} is unavailable; cannot find the state before operation {}",
            before_uuid,
            operation.id
        );
    };
    if op.affected.is_empty() {
        info!("history: operation {} touched nothing", operation.id);
        return Ok(());
    }
    let paths: Vec<PathBuf> = op
        .affected
        .iter()
        .map(|path| normalize_target(Path::new(path)))
        .collect();
    let message = format!(
        "undid {} {} ({})",
        op.kind.as_str(),
        operation.id,

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Restore via rollback with explicit paths from an available checkpoint instead of undo
  2. Extend history retention / avoid pruning the protective checkpoints of recent operations
  3. Check `mise bootstrap dotfiles history` for which checkpoints remain and pick an available ref

Example fix

// before
mise bootstrap dotfiles undo   # before-checkpoint pruned
// after
mise bootstrap dotfiles history            # find available checkpoints
mise bootstrap dotfiles rollback --to <available-ref> --all
Defensive patterns

Strategy: validation

Validate before calling

const entries = await listHistory();
const op = /* selected operation */;
if (op?.checkpoint?.operation?.before &&
    !entries.some(e => e.checkpoint.uuid === op.checkpoint.operation.before)) {
  throw new Error(`before-checkpoint ${op.checkpoint.operation.before} unavailable`);
}

Type guard

const beforeExists = (before: string | undefined, entries: HistoryEntry[]): before is string =>
  typeof before === "string" && entries.some(e => e.checkpoint.uuid === before);

Try / catch

try {
  await undo();
} catch (e) {
  if (String(e).includes("is unavailable")) {
    console.error("Protective checkpoint pruned; use rollback with an available ref.");
  } else throw e;
}

Prevention

When it happens

Trigger: Running undo when entries.iter().find(|e| e.checkpoint.uuid == before_uuid) returns None — the before-checkpoint was pruned from history, the store was rebuilt/gc'd, or UUIDs changed after re-import.

Common situations: History pruning/gc removed old checkpoints; user moved or recreated the dotfiles git store; syncing history between machines dropped entries.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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