{"record":{"id":"96d089719ace29cd","repo":"jdx/mise","slug":"write-completion-was-not-recorded-inspect-the-liv","errorCode":null,"errorMessage":"write completion was not recorded; inspect the live file before retrying recovery","messagePattern":"write completion was not recorded; inspect the live file before retrying recovery","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/recovery.rs","lineNumber":83,"sourceCode":"    state_dir: &Path,\n    path: &Path,\n    prior: &PathSnapshot,\n    after: Option<&PathState>,\n) -> Result<()> {\n    validate_destination(path)?;\n    let comparison = tempfile::tempdir()?;\n    let depth = if matches!(prior, PathSnapshot::Directory { .. }) {\n        Capture::Shallow\n    } else {\n        Capture::Full\n    };\n    // Comparing must not leave copies of concurrent user edits in the store.\n    let current = PathSnapshot::capture_with(comparison.path(), path, depth);\n    if !matches!(prior, PathSnapshot::Unrecorded { .. }) && &current == prior {\n        return Ok(());\n    }\n    let Some(after) = after else {\n        bail!(\"write completion was not recorded; inspect the live file before retrying recovery\");\n    };\n    if PathState::observe(path) != *after {\n        bail!(\"changed after the operation; left untouched\");\n    }\n    // Entry count alone cannot establish a directory's identity. Never\n    // replace a populated directory on that evidence.\n    if matches!(after, PathState::Dir { entries, .. } if *entries != 0)\n        && !(matches!(prior, PathSnapshot::Directory { .. })\n            && matches!(\n                after,\n                PathState::Dir {\n                    identity: Some(_),\n                    ..\n                }\n            ))\n    {\n        bail!(\"directory contents cannot be verified safely; left untouched\");\n    }","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/recovery.rs#L65-L101","documentation":"recover_path first checks whether the live file already matches the recorded prior snapshot (nothing to do). If recovery must proceed but the operation's 'after' state was never recorded, it cannot know the intended final state and bails, telling the user to inspect the live file rather than guessing.","triggerScenarios":"recover_path invoked via recover_entries with after == None for the path, and the current file differs from the prior snapshot — i.e. the original operation crashed before recording its completion state.","commonSituations":"A hard kill/power loss during a dotfile write left no completion checkpoint; recovery data written partially; retrying recovery of an operation that never got far enough to snapshot its result.","solutions":["Manually inspect the live file at the reported path and confirm it is correct.","If current contents are correct, accept them with `recover <operation> --keep-current`.","If contents are wrong, restore the intended content manually, then retry recovery.","Re-run bootstrap enrollment to rebuild the recovery/checkpoint state."],"exampleFix":"// before: blind retry\n$ mise bootstrap dotfiles recover\n// after: verify the live file first, then accept it\n$ cat ~/.zshrc  # inspect\n$ mise bootstrap dotfiles recover <operation> --keep-current","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = recover_entries(state_dir, plan) {\n    if e.to_string().contains(\"write completion was not recorded\") {\n        eprintln!(\"inspect the listed live file, then rerun with --keep-current\");\n    }\n}","preventionTips":["Avoid killing mise mid-write (use graceful termination).","Verify the live file's content immediately after a crash before recovery.","Prefer --keep-current over blind retries when completion state is missing."],"tags":["recovery","dotfiles","missing-state","crash"],"backgroundTag":"record-not-found","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}