{"record":{"id":"1b6e5eb46b44df45","repo":"jdx/mise","slug":"origin-changed-while-planning-reconcile-again","errorCode":null,"errorMessage":"origin changed while planning; reconcile again","messagePattern":"origin changed while planning; reconcile again","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/run.rs","lineNumber":701,"sourceCode":"    // turn an ordinary incoming edit into an unrelated adoption conflict.\n    let heads = super::graph::Heads::read(repo)?;\n    status.upstream_commit = heads.remote.clone();\n    status.pending_repository = match &heads.local {\n        Some(local) => {\n            crate::system::history::manifest::Manifest::read(repo, local)?.as_ref()\n                != Some(&tracked.manifest)\n        }\n        None => heads.remote.is_some(),\n    };\n    let repository_tree = incoming_repository_tree(repo, tracked)\n        .inspect_err(|error| repository_conflict(status, error))?;\n    status.pending_repository |= repository_tree.is_some();\n    if let Some(tree) = repository_tree.as_deref().or(heads.remote.as_deref()) {\n        super::directories::plan(repo, tracked, tree)\n            .inspect_err(|error| repository_conflict(status, error))?;\n    }\n    if heads.remote != upstream.commit {\n        bail!(\"origin changed while planning; reconcile again\");\n    }\n    let baseline = reconcile::upstream(repo, heads.base.as_deref())?;\n    let local_manifest = heads\n        .local\n        .as_deref()\n        .map(|head| crate::system::history::manifest::Manifest::read(repo, head))\n        .transpose()?\n        .flatten()\n        .unwrap_or_default();\n    let sync_state: state::SyncState = baseline\n        .files\n        .into_iter()\n        .map(|(path, object)| {\n            (\n                path,\n                state::SyncRecord {\n                    acknowledged: Some(object.clone()),\n                    reconciled: Some(object.clone()),","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/sync/run.rs#L683-L719","documentation":"During prepare, mise re-checks that the origin head recorded in the sync status (upstream.commit) still matches the remote head read from the repository (heads.remote) after planning directory changes. If they diverged, the plan is based on a stale view of origin, so mise aborts and asks for a fresh reconcile.","triggerScenarios":"Running sync/pull where the remote head moved (or the status commit changed) between reading status and planning — e.g. a concurrent fetch/pull updated heads, or another machine pushed to origin while this prepare was running.","commonSituations":"Another machine pushed to the setup branch mid-sync; a concurrent `mise dot pull` refreshed heads while a sync was preparing; reconnecting to a different origin without re-pulling first.","solutions":["Re-run `mise dot sync` so planning happens with freshly fetched heads.","Ensure no other sync/pull is running concurrently, then retry.","If origin genuinely moved, run `mise dot pull` first to reconcile with the new origin head, then sync."],"exampleFix":"// before: origin moved during prepare\nmise dot sync // error: origin changed while planning\n// after: reconcile first, then sync\nmise dot pull\nmise dot sync","handlingStrategy":"retry","validationCode":"// confirm origin head still matches the recorded status commit before syncing\nlet heads = Heads::read(repo)?;\nif heads.remote != upstream.commit {\n    eprintln!(\"origin moved; run `mise dot pull` first\");\n    return;\n}","typeGuard":"fn origin_consistent(heads: &Heads, upstream: &Upstream) -> bool {\n    heads.remote == upstream.commit\n}","tryCatchPattern":"match sync() {\n    Err(e) if e.to_string().contains(\"origin changed while planning\") => { pull(); sync(); }\n    other => other,\n}","preventionTips":["Serialize sync and pull; never run them concurrently.","Pull after known upstream changes (other machines pushing) before syncing.","Re-run sync after any origin reconfiguration rather than continuing an in-flight one."],"tags":["sync","concurrency","git","stale-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}