jdx/mise · error
incoming files changed while preparing adoption; plan again
Error message
incoming files changed while preparing adoption; plan again
What it means
candidate() mirrors the local-side check for adoption: when only a remote commit exists, it verifies the remote commit's output tree still matches the tree captured when planning. If incoming files changed on origin between planning and applying, the adoption plan is stale and applying it could clobber newer incoming content, so it aborts.
Source
Thrown at src/system/history/sync/graph.rs:61
remote,
base,
})
}
/// Preparing a candidate does not advance a branch or write live files.
/// The caller must finish its complete application before adopting it.
pub(crate) fn candidate(&self, repo: &HistoryRepo, tree: &str) -> Result<Option<Candidate>> {
let commit = match (&self.local, &self.remote) {
(None, None) => return Ok(None),
(Some(local), None) => {
if repo.output_tree_of(local)? != tree {
bail!("saved files changed while preparing publication; plan again");
}
local.clone()
}
(None, Some(remote)) => {
if repo.output_tree_of(remote)? != tree {
bail!("incoming files changed while preparing adoption; plan again");
}
remote.clone()
}
(Some(local), Some(remote)) => {
if self.base.as_ref() == Some(remote) {
if repo.output_tree_of(local)? != tree {
bail!("saved files changed while preparing publication; plan again");
}
local.clone()
} else if self.base.as_ref() == Some(local) && repo.output_tree_of(remote)? == tree
{
remote.clone()
} else {
repo.commit_tree(tree, vec![local, remote], "merge origin dotfiles")?
}
}
};
Ok(Some(Candidate {View on GitHub (pinned to afd2eddd3a)
Solutions
- Re-fetch origin and rebuild the adoption plan against the latest remote tree.
- Retry the adoption after the concurrent push completes.
- Coordinate pushes so only one machine publishes at a time (or re-run pull immediately before adopting).
Example fix
# before: plan from stale origin state $ mise bootstrap dotfiles pull # fails: incoming files changed # after: refetch and re-plan $ git -C ~/.local/share/mise/history fetch origin $ mise bootstrap dotfiles pull
Defensive patterns
Strategy: retry
Validate before calling
if repo.output_tree_of(remote_commit)? != planned_tree {
eprintln!("origin tree advanced; refetch and replan adoption");
} Try / catch
match candidate(plan, repo, &tree) {
Ok(c) => adopt(c),
Err(e) if e.to_string().contains("plan again") => {
fetch_origin()?;
replan_and_adopt(repo)
}
Err(e) => return Err(e),
} Prevention
- Fetch origin immediately before planning adoption.
- Coordinate with other machines to avoid concurrent pushes.
- Retry adoption promptly rather than leaving plans open during long interactions.
When it happens
Trigger: Calling candidate() with (local, remote)=(None, Some) where repo.output_tree_of(remote) != the tree argument — origin's saved files advanced after the plan was built.
Common situations: Another machine pushed to the origin store while this machine was preparing adoption; a slow interactive confirmation window during which a fetch brought in newer commits; scheduled CI pushing dotfile changes concurrently.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- setup history changed during adoption; retry pull
- {} changed before application; nothing was written
- {} changed while the changes were being applied; nothing mor
- {} changed during setup adoption; retry pull
- saved files changed while preparing publication; plan again
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/e2da3369a4a9f6c1.
Report an issue: GitHub.