jdx/mise · error
cannot protect {}: {reason}
Error message
cannot protect {}: {reason} What it means
When taking a history snapshot (`snapshot` in preimages.rs), each path resolves to a `PathSnapshot`. If a path is `Unrecorded` for some `reason` (e.g. unreadable, unsupported) but is still considered `eligible` for protection, mise cannot safely include it and bails with `cannot protect {path}: {reason}` instead of silently dropping a file it promised to protect.
Source
Thrown at src/system/history/checkpoint/preimages.rs:244
for link in links {
self.snapshot(
&path.join(&link.rel),
&PathSnapshot::Symlink {
dest: link.dest.clone(),
},
tree,
)?;
}
}
}
PathSnapshot::Directory { mode } => {
if self.eligible(path)? {
self.mode(path, Some(*mode));
}
}
PathSnapshot::Unrecorded { reason, .. } => {
if self.eligible(path)? {
eyre::bail!("cannot protect {}: {reason}", display_path(path));
}
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::system::files::{FileMode, FilePolicy};
use crate::system::history::journal::Capture;
#[test]
fn first_preimages_survive_multiple_phases_without_saving_siblings() -> Result<()> {
let state = tempfile::tempdir()?;
let live =
tempfile::tempdir_in(crate::system::history::sync::layout::Roots::current().home)?;View on GitHub (pinned to afd2eddd3a)
Solutions
- Fix the underlying reason shown in the message (e.g. `chmod`/`chown` the file so it's readable by the current user).
- Exclude the problematic path from history tracking/config protection scope.
- Restore the missing file if it disappeared mid-snapshot, then retry the snapshot.
Example fix
# before: file unreadable ls -l ~/.config/mise/secrets.toml # -rw------- root root # after sudo chown $USER ~/.config/mise/secrets.toml && chmod u+rw ~/.config/mise/secrets.toml
Defensive patterns
Strategy: try-catch
Validate before calling
if !path.exists() || std::fs::metadata(&path).map(|m| m.permissions().readonly()).unwrap_or(true) {
exclude_from_tracking(&path);
} Try / catch
match result {
Err(e) if e.to_string().starts_with("cannot protect") => fix_or_exclude(&path)?,
other => other?,
} Prevention
- Ensure tracked files are readable by the user running mise
- Exclude special/unreadable files from history tracking
- Fix or restore files reported in the error message before retrying snapshots
When it happens
Trigger: A path passes `eligible()` (so it's in the protection set) but its snapshot classification is `PathSnapshot::Unrecorded { reason, .. }` — e.g. unreadable file, permission issue, or unsupported file type discovered during snapshotting.
Common situations: A config/tracked file has restrictive permissions (mode 600 owned by another user), a file was deleted between listing and snapshotting, or a symlink/special file cannot be recorded.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- {other:?}
- no protective checkpoint could be taken; nothing was changed
- cannot capture non-file {}
- rustc output is not a regular file: {}
- failed to create file symlink: {err}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/b2de4288ae878313.
Report an issue: GitHub.