{"record":{"id":"9e943e4afd1566cb","repo":"jdx/mise","slug":"no-usable-preimage-reason","errorCode":null,"errorMessage":"no usable preimage: {reason}","messagePattern":"no usable preimage: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/recovery.rs","lineNumber":188,"sourceCode":"                }\n            }\n            for leaf in files\n                .iter()\n                .map(|f| &f.rel)\n                .chain(links.iter().map(|f| &f.rel))\n            {\n                if seen\n                    .iter()\n                    .any(|other| *other != leaf && other.starts_with(leaf))\n                {\n                    bail!(\"recovery directory descends through a file or symlink\");\n                }\n            }\n            for file in files {\n                read_blob(state_dir, &file.content)?;\n            }\n        }\n        PathSnapshot::Unrecorded { reason, .. } => bail!(\"no usable preimage: {reason}\"),\n        _ => {}\n    }\n    Ok(())\n}\n\nfn remove_leaf(path: &Path) -> Result<()> {\n    match std::fs::symlink_metadata(path) {\n        Ok(meta) if meta.is_dir() => std::fs::remove_dir(path)?,\n        Ok(_) => std::fs::remove_file(path)?,\n        Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}\n        Err(error) => return Err(error.into()),\n    }\n    Ok(())\n}\n\nfn set_mode(path: &Path, mode: u32) -> Result<()> {\n    #[cfg(unix)]\n    {","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/recovery.rs#L170-L206","documentation":"When the recorded preimage is PathSnapshot::Unrecorded, the journal explicitly states that the path's prior content was never captured (with a reason), so there is nothing to restore. validate_snapshot bails early with that reason instead of attempting a restore. This is informational-by-design: recovery cannot undo a write whose original state is unknown.","triggerScenarios":"recover_path -> validate_snapshot on a prior snapshot of variant Unrecorded { reason, .. } — the write operation intentionally skipped preimage capture (e.g. preimage too large, unreadable, or excluded by policy at operation time).","commonSituations":"The original write hit a file that was unreadable or excluded from capture when the operation ran; running recovery later for that operation finds no preimage to roll back to.","solutions":["Read the embedded `reason` in the message to learn why the preimage was not recorded.","Accept the file's current contents with `recover <operation> --keep-current`, or restore the desired content manually from your dotfiles repo.","For future operations, ensure target files are readable and within capture limits so preimages get recorded."],"exampleFix":"// before\nerror: ~/.config/large.bin: no usable preimage: preimage exceeded capture size limit\n\n// after (accept current contents)\n$ mise bootstrap dotfiles recover <operation> --keep-current","handlingStrategy":"try-catch","validationCode":"// inspect the snapshot variant before recovery to know if rollback is possible\nif matches!(prior, PathSnapshot::Unrecorded { .. }) {\n    eprintln!(\"no preimage recorded; rollback impossible -- plan manual restore\");\n}","typeGuard":null,"tryCatchPattern":"match recover(&state_dir, &journal) {\n    Err(e) if e.to_string().contains(\"no usable preimage\") => {\n        // accept current contents: mise bootstrap dotfiles recover <op> --keep-current\n    }\n    other => other?,\n}","preventionTips":["Ensure target files are readable and within capture size limits before running write operations","Keep a VCS or backup of dotfiles so unrecorded preimages can be restored manually","Read the embedded reason in the message to understand why capture was skipped"],"tags":["preimage","snapshot","recovery","undo"],"backgroundTag":"missing-required-data","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}