jdx/mise · error
local saved history changed while planning; reconcile again
Error message
local saved history changed while planning; reconcile again
What it means
Before publishing saved history, mise re-reads the shadow repository's heads and compares the local head against the value captured when the plan was built (`expected_local`). If the local branch moved between planning and publication — another sync, pull, or local write happened concurrently — mise aborts and asks the user to reconcile again, preventing publication based on stale assumptions.
Source
Thrown at src/system/history/sync/publish.rs:20
use eyre::{Result, bail};
use std::collections::BTreeSet;
use super::graph::Heads;
use super::network::{PushOutcome, Remote};
use crate::system::history::shadow::HistoryRepo;
/// Reconciliation and complete live application must precede publication.
/// A merge that still changes this machine's saved tree needs another pull.
pub(crate) fn build(
repo: &HistoryRepo,
upstream: Option<&str>,
expected_local: Option<&str>,
accepted: &BTreeSet<String>,
) -> Result<Option<String>> {
let heads = Heads::read(repo)?;
if heads.local.as_deref() != expected_local {
bail!("local saved history changed while planning; reconcile again");
}
if heads.remote.as_deref() != upstream {
bail!("origin changed while preparing publication; reconcile again");
}
let Some(local) = &heads.local else {
return Ok(None);
};
if heads.remote.as_ref() == Some(local) {
return Ok(None);
}
let tree = repo.output_tree_of(local)?;
if let Some(remote) = &heads.remote
&& heads.base.as_ref() != Some(remote)
{
let (mut merged, mut conflicts) = repo.merge_tree(local, remote)?;
// Enrollment is a keyed inventory, not arbitrary JSON text. Git's
// line merge can conflict on independent additions or combine policy
// changes into invalid metadata. Validate its structured merge first.View on GitHub (pinned to afd2eddd3a)
Solutions
- Re-run the reconcile/plan step (`mise bootstrap dotfiles pull` or equivalent) so `expected_local` is refreshed, then publish again.
- Ensure no other mise sync process is running concurrently (single writer).
- If it recurs, serialize sync operations (script them sequentially) rather than invoking pull and publish in parallel.
Example fix
// before: prepare and publish interleaved with another process mise bootstrap dotfiles publish & mise bootstrap dotfiles pull # moves local head -> stale expected_local // after mise bootstrap dotfiles pull && mise bootstrap dotfiles publish # sequential, no concurrency
Defensive patterns
Strategy: retry
Validate before calling
const heads = await readHeads();
if (heads.local !== expectedLocal) {
console.warn("local head moved; rerun reconcile before publishing");
} Try / catch
try {
await publish();
} catch (e) {
if (String(e.message).includes("changed while planning")) {
await reconcile();
await publish(); // retry once with a fresh plan
} else throw e;
} Prevention
- Run only one mise sync operation at a time; avoid concurrent pull/publish.
- Minimize the delay between plan and publish.
- Disable background sync jobs while publishing manually.
When it happens
Trigger: In publish `build`, `Heads::read(repo).local != expected_local`. Triggered by any concurrent modification of the saved-history branch between the plan/prepare step and the publish step: another mise process pulling or committing, or a changed accepted set applied locally in the meantime.
Common situations: Two terminals running mise bootstrap dotfiles pull/publish at once; a background sync job committed saved history while the user was publishing; the user ran a reconcile between the prepare and publish commands.
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
- incoming files changed while preparing adoption; plan again
- origin changed while preparing publication; reconcile again
- origin changed while planning; reconcile again
- {} changed before application; nothing was written
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/654510ff8117ac5d.
Report an issue: GitHub.