{"record":{"id":"62ab201fe4e6e8e1","repo":"GitoxideLabs/gitoxide","slug":"could-not-atomically-move-references-and-the-undo","errorCode":null,"errorMessage":"could not atomically move references and the undo cursor","messagePattern":"could not atomically move references and the undo cursor","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/undo.rs","lineNumber":105,"sourceCode":"                &transition.workdir,\n                transition.old,\n                transition.new,\n            )\n            .context(\"local changes prevent undo/redo; stash them manually and retry\")?;\n        }\n        for (applied, transition) in transitions.iter().enumerate() {\n            if let Err(err) = super::forget::apply_tree_transition(&transition.workdir, transition.old, transition.new)\n            {\n                return Err(rollback_transitions(\n                    &transitions[..=applied],\n                    err.context(\"could not align a worktree with the undo queue\"),\n                ));\n            }\n        }\n        if let Err(err) = repo.edit_references(self.edits) {\n            return Err(rollback_transitions(\n                &transitions,\n                anyhow::Error::new(err).context(\"could not atomically move references and the undo cursor\"),\n            ));\n        }\n        Ok(())\n    }\n}\n\npub(crate) fn is_queue_ref(name: &BStr) -> bool {\n    name.as_bytes() == TIP_REF.as_bytes() || name.as_bytes() == CURSOR_REF.as_bytes()\n}\n\npub(crate) fn ref_chain_reaches_queue(repo: &gix::Repository, name: &FullNameRef) -> Result<bool> {\n    let mut name = name.to_owned();\n    let mut seen = HashSet::new();\n    loop {\n        if is_queue_ref(name.as_bstr()) {\n            return Ok(true);\n        }\n        ensure!(seen.insert(name.clone()), \"a symbolic reference chain contains a cycle\");","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/undo.rs#L87-L123","documentation":"When applying an undo, `edit_references()` failed to atomically move references and the undo cursor. Because the failure occurred after transitions were prepared, the prepared transitions are rolled back and the original error is wrapped with this context. It signals the atomic reference update could not be committed.","triggerScenarios":"`Repository::edit_references()` returns an error during `apply_with_worktrees()` — e.g. reference updates rejected by the ref store (lock contention, non-fast-forward against expectations, failing ref transaction).","commonSituations":"Concurrent modification of refs while undoing; refs changed by another process between undo capture and apply; filesystem permission or lock issues in `.git/refs`.","solutions":["Re-run the undo after re-checking that refs are unchanged (the undo snapshot may be stale)","Inspect the wrapped source error to find the underlying ref-transaction failure (locks, permissions, ref shape)","Retry when the cause is transient lock contention"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before applying, verify refs still match the undo snapshot\nfor (ref_path, expected) in &snapshot.refs {\n    if repo.find_reference(ref_path).map(|r| r.id()) != Ok(expected) {\n        // undo is stale; refresh or abort\n    }\n}","typeGuard":null,"tryCatchPattern":"if let Err(err) = undo.apply(&mut repo) {\n    let cause: Option<&(dyn std::error::Error + 'static)> = err.source();\n    while let Some(c) = cause {\n        eprintln!(\"caused by: {c}\");\n        cause = c.source();\n    }\n    // rollback happened; refresh undo snapshot and retry\n}","preventionTips":["Re-verify ref state immediately before applying an undo","Avoid concurrent git processes mutating refs during undo application","Keep undo snapshots short-lived and refresh them when refs change"],"tags":["rust","git","refs","atomicity","undo"],"backgroundTag":"git-command-failed","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}