jdx/mise · error
directory contents cannot be verified safely; left untouched
Error message
directory contents cannot be verified safely; left untouched
What it means
When the recorded 'after' state is a non-empty directory (or the prior state was not itself a directory), entry counts alone cannot prove the directory's identity, so recovery refuses to act to avoid clobbering unknown contents. It bails before restore, also after re-checking that the path still matches the 'after' state.
Source
Thrown at src/system/history/recovery.rs:100
let Some(after) = after else {
bail!("write completion was not recorded; inspect the live file before retrying recovery");
};
if PathState::observe(path) != *after {
bail!("changed after the operation; left untouched");
}
// Entry count alone cannot establish a directory's identity. Never
// replace a populated directory on that evidence.
if matches!(after, PathState::Dir { entries, .. } if *entries != 0)
&& !(matches!(prior, PathSnapshot::Directory { .. })
&& matches!(
after,
PathState::Dir {
identity: Some(_),
..
}
))
{
bail!("directory contents cannot be verified safely; left untouched");
}
validate_snapshot(state_dir, prior)?;
if PathState::observe(path) != *after {
bail!("changed while preparing recovery; left untouched");
}
restore(state_dir, path, prior)
}
fn validate_destination(path: &Path) -> Result<()> {
if !path.is_absolute() || path.components().any(|c| matches!(c, Component::ParentDir)) {
bail!("invalid recovery destination");
}
for parent in path.ancestors().skip(1) {
if std::fs::symlink_metadata(parent).is_ok_and(|meta| meta.is_symlink()) {
bail!("a parent directory is now a symlink; left untouched");
}
}
Ok(())View on GitHub (pinned to afd2eddd3a)
Solutions
- Manually inspect the directory contents; remove or move files you do not need, then retry recovery.
- Use `recover <operation> --keep-current` to explicitly accept the directory's current contents.
- Recreate the directory structure via re-running bootstrap/enrollment instead of automatic restore.
- Restore the directory from backup if its contents are wrong.
Example fix
// before: populated dir blocks auto-restore $ mise bootstrap dotfiles recover // after: review the dir, then accept current contents $ ls ~/.config/tool/ $ mise bootstrap dotfiles recover <operation> --keep-current
Defensive patterns
Strategy: validation
Validate before calling
// before recovering, ensure the directory is reviewable
let populated = std::fs::read_dir(path).map(|d| d.count() > 0).unwrap_or(false);
if populated { eprintln!("review contents; consider --keep-current"); } Try / catch
match recover_entries(state_dir, plan) {
Err(e) if e.to_string().contains("cannot be verified safely") => {
eprintln!("{e}\ninspect the directory manually, then use --keep-current");
}
other => other?,
} Prevention
- Avoid interrupting operations that replace whole directories.
- Don't add files into directories pending recovery.
- Review populated directories manually before automatic restore.
When it happens
Trigger: recover_path invoked where `after` is PathState::Dir with entries != 0 and it is not the case that both `prior` and the observed state were identity-verified directories — i.e. a populated directory whose contents cannot be validated against the snapshot.
Common situations: Recovering an interrupted operation that replaced a populated directory (e.g. a config folder) where the crash left no verifiable identity; user files added inside the directory since the operation; restoring directories whose entries were never fully snapshotted.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- no matching interrupted operation; `mise bootstrap dotfiles
- select one operation by its identifier before accepting curr
- operation {} still needs attention; its pending record was p
- interrupted file recovery needs attention; temporary recover
- write completion was not recorded; inspect the live file bef
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/72c0fb5302d21a63.
Report an issue: GitHub.