{"record":{"id":"cea69320f088a0ad","repo":"jdx/mise","slug":"checkpoint-has-no-protective-checkpoint-to-undo","errorCode":null,"errorMessage":"checkpoint {} has no protective checkpoint to undo from","messagePattern":"checkpoint (.+?) has no protective checkpoint to undo from","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/replay.rs","lineNumber":289,"sourceCode":"    let Some(op) = operation.checkpoint.operation.clone() else {\n        bail!(\"checkpoint {} is not an operation\", operation.id);\n    };\n    // Undo restores tracked files only, never package or service state.\n    if op.status == OperationStatus::Pending {\n        bail!(\n            \"checkpoint {} is still running or was interrupted; nothing to undo\",\n            operation.id\n        );\n    }\n    if op.status == OperationStatus::Failed && !op.affected.is_empty() {\n        info!(\n            \"history: operation {} failed midway; reversing the {} path(s) it changed\",\n            operation.id,\n            op.affected.len()\n        );\n    }\n    let Some(before_uuid) = &op.before else {\n        bail!(\n            \"checkpoint {} has no protective checkpoint to undo from\",\n            operation.id\n        );\n    };\n    let Some(before) = entries\n        .iter()\n        .find(|entry| &entry.checkpoint.uuid == before_uuid)\n        .cloned()\n    else {\n        bail!(\n            \"checkpoint {} is unavailable; cannot find the state before operation {}\",\n            before_uuid,\n            operation.id\n        );\n    };\n    if op.affected.is_empty() {\n        info!(\"history: operation {} touched nothing\", operation.id);\n        return Ok(());","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/replay.rs#L271-L307","documentation":"Undo restores files from the 'before' protective checkpoint recorded on the operation. If the operation has no `before` checkpoint reference, undo cannot know what the files looked like beforehand and fails rather than guessing.","triggerScenarios":"Undoing a failed operation whose `op.before` is `None` — an operation that never captured a pre-operation snapshot (e.g. created before the protective-checkpoint mechanism, or snapshot capture failed).","commonSituations":"Old history entries created by a mise version without protective checkpoints; a corrupted or pruned history store losing the before-reference; undoing the very first entry in a freshly initialized history.","solutions":["Manually restore the files from your own backup or git, then run `mise dot checkpoint`-style sync to re-baseline","Drop the stale entry from history (or prune history) so undo targets valid operations instead","Upgrade/re-run operations with a current mise version so future checkpoints capture `before` state"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"const op = entry?.operation;\nif (op && !op.before) throw new Error('no protective before-checkpoint; restore manually');","typeGuard":null,"tryCatchPattern":"try {\n  await mise.dot.undo();\n} catch (e) {\n  if (/no protective checkpoint/.test(e.message)) {\n    // fall back to manual restore from backup/git\n  }\n}","preventionTips":["Keep mise up to date so operations always capture before-state","Regularly back up the dotfiles history store","Avoid hand-editing or pruning history entries"],"tags":["dotfiles","undo","git"],"backgroundTag":"record-not-found","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}