jdx/mise · error
checkpoint {} has no protective checkpoint to undo from
Error message
checkpoint {} has no protective checkpoint to undo from What it means
Every undoable operation records a protective `before` checkpoint UUID capturing the state prior to the operation. Undo restores from that checkpoint; if op.before is None the protective snapshot was never recorded, so there is no state to restore to and mise bails.
Source
Thrown at src/system/history/replay.rs:289
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",
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(());View on GitHub (pinned to afd2eddd3a)
Solutions
- Use rollback with explicit paths or `--to <ref> --all` to restore files from a known checkpoint instead
- Check `mise bootstrap dotfiles history` for checkpoints that do have before-state
- If the store is corrupted, re-initialize dotfiles tracking and re-snapshot
Example fix
// before mise bootstrap dotfiles undo # operation lacks before-checkpoint // after mise bootstrap dotfiles rollback --to <known-ref> --all
Defensive patterns
Strategy: validation
Validate before calling
const entry = await getCheckpoint(id);
if (entry?.checkpoint?.operation && !entry.checkpoint.operation.before) {
throw new Error(`checkpoint ${id} has no protective before-checkpoint`);
} Type guard
const hasBefore = (op: Operation): op is Operation & { before: string } =>
typeof op.before === "string" && op.before.length > 0; Try / catch
try {
await undo();
} catch (e) {
if (String(e).includes("no protective checkpoint")) {
await rollback({ paths: knownPaths });
} else throw e;
} Prevention
- Ensure operations always create the pre-operation snapshot
- Migrate history created by older versions lacking before refs
- Fall back to rollback when before-state is absent
When it happens
Trigger: Running undo against an operation whose op.before is None — the operation was created without a pre-operation snapshot (older format, snapshot skipped, or corrupted record).
Common situations: History entries created by an older mise version before protective checkpoints were recorded; manually edited/corrupted history store; operations that bypassed checkpoint creation.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- checkpoint {} is not an operation
- checkpoint {} is still running or was interrupted; nothing t
- checkpoint {} is unavailable; cannot find the state before o
- expected a checkpoint
- checkpoint {} has no content snapshot
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/cea69320f088a0ad.
Report an issue: GitHub.