jdx/mise · error
cannot safely change
Error message
cannot safely change {} without a recovery preimage: {reason} What it means
`begin_changes_with` captures pre-change snapshots of configured paths so changes can be reverted. In a scope that `requires_recovery_preimage()` (a strict/recovery mode), a path whose prior state is `PathSnapshot::Unrecorded` (e.g. the file could not be captured, does not exist in STATE, or the capture backend was unavailable) makes a safe change impossible, so it aborts instead of proceeding without a rollback image.
Solutions
- Run the non-strict bootstrap path first so the path gets a recorded preimage (the same code falls back to a warning when recovery is not required)
- Create/restore the target file at the expected location before beginning changes
- Fix read permissions on the path for the user running the tool
- Inspect the `{reason}` in the message to identify which capture condition failed and address it directly
Example fix
// before
begin_changes_with(paths)?; // fails in recovery scope
// after
if !path.exists() { fs::create(path)?; }
begin_changes_with(paths)?; Defensive patterns
Strategy: validation
Validate before calling
// verify each path is capturable before beginning changes
for path in paths {
let snap = PathSnapshot::capture_with(&dirs::STATE, &path, capture);
if let PathSnapshot::Unrecorded { reason, .. } = snap {
if requires_recovery_preimage() {
return Err(format!("{path}: {reason}"));
}
}
} Try / catch
match begin_changes_with(paths) {
Err(e) if e.to_string().starts_with("cannot safely change") => {
// bootstrap/repair the path, then retry once
}
other => other,
} Prevention
- Run the non-strict bootstrap at least once so all managed paths have recorded preimages
- Check path existence and readability before beginning changes in recovery scopes
- Keep files managed by this tool from being deleted/moved externally between planning and capture
When it happens
Trigger: Calling `begin_changes_with` (via `begin_changes`) while in a recovery-requiring scope and a target path's snapshot returns `Unrecorded { reason, .. }` — e.g. the path does not exist yet, permission to read it failed, or no prior recorded state exists in `dirs::STATE`.
Common situations: Running a deployment/recovery operation against files that were never bootstrapped into history state; files deleted or moved between planning and capture; read-permission problems under a different user or sandbox.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- brew-cask: unresolved recovery for newly created target
- brew-cask: unresolved recovery for
- cannot capture non-file
- cannot encrypt non-file
- cannot protect
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/0358a2c4098adbd4.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/history/journal.rs:534
}
/// [`begin_changes`] with a capture depth per path. Fails when an entry
/// cannot be persisted: the mutation must not go ahead without its
/// write-ahead record.
pub(crate) fn begin_changes_with(
part: &str,
item: &str,
paths: impl IntoIterator<Item = (PathBuf, Capture)>,
) -> Result<Vec<PendingChange>> {
if !super::scope::is_active() {
return Ok(vec![]);
}
let mut pending = vec![];
for (path, capture) in paths {
let prior = PathSnapshot::capture_with(&dirs::STATE, &path, capture);
if let PathSnapshot::Unrecorded { reason, .. } = &prior {
if super::scope::requires_recovery_preimage() {
eyre::bail!(
"cannot safely change {} without a recovery preimage: {reason}",
display_path(&path)
);
}
warn!(
"bootstrap: temporary recovery is unavailable for {}: {reason}; proceeding with deployment",
display_path(&path)
);
}
if let Some(seq) = super::scope::record(JournalEntry::PathChanged {
part: part.to_string(),
item: item.to_string(),
path: path.clone(),
prior,
})? {
pending.push(PendingChange { seq, path });
}
}View on GitHub (pinned to 533346cc37)