jdx/mise · error

these paths keep changing while being protected; nothing was

Error message

these paths keep changing while being protected; nothing was changed: {}

What it means

During protection, replay verifies captured paths across multiple rounds (VERIFY_ROUNDS). If paths are still 'missing' from the capture after the last round, the tree is changing underneath mise, so it aborts before applying anything.

Source

Thrown at src/system/history/replay.rs:533

            .checkpoint
            .tree
            .snapshot
            .clone()
            .ok_or_else(|| eyre::eyre!("the protective checkpoint has no content"))?;
        let mut missing = vec![];
        for step in steps.iter().filter(|step| step.action.mutates()) {
            let Some(current) = repo.restored_object_at(&live, &step.tree_path)? else {
                continue;
            };
            if repo.restored_object_at(&before_tree, &step.tree_path)? != Some(current) {
                missing.push(step.path.clone());
            }
        }
        if missing.is_empty() {
            break;
        }
        if round >= VERIFY_ROUNDS {
            bail!(
                "these paths keep changing while being protected; nothing was changed: {}",
                missing
                    .iter()
                    .map(display_path)
                    .collect::<Vec<_>>()
                    .join(", ")
            );
        }
        warn!(
            "history: {} path(s) changed after the protective checkpoint; capturing again",
            missing.len()
        );
        scope.recapture_before(&missing)?;
    }
    let mut touched = vec![];
    // deletions deepest first, then writes shallowest first: a directory is
    // emptied before the file that replaces it is written, and a directory
    // that replaces a file exists before its files are written

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Stop active writers (dev servers, watchers, sync clients) and re-run the replay
  2. Identify and exclude the churning paths listed in the message
  3. Retry when the working tree is quiet
Defensive patterns

Strategy: retry

Validate before calling

// before replay, check tree stability: hash the tree twice with a delay
let a = tree_fingerprint(root);
std::thread::sleep(Duration::from_secs(1));
let b = tree_fingerprint(root);
assert_eq!(a, b, "working tree is churning; stop writers first");

Try / catch

// retry after quiescing writers
for _ in 0..3 {
    match apply_steps(...) {
        Err(e) if e.to_string().contains("keep changing while being protected") => {
            stop_watchers();
            continue;
        }
        r => break r,
    }
}

Prevention

When it happens

Trigger: Paths that must be protected keep appearing/disappearing during the verify rounds — files are created, deleted, or renamed faster than the capture+verify loop can converge within VERIFY_ROUNDS iterations.

Common situations: A dev server, watcher, build, or test suite actively writing into the project while a history replay runs; flaky sync tools (Dropbox/OneDrive) churning files.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/cd3256b97895bb03. Report an issue: GitHub.