{"record":{"id":"a85d8e5089394df9","repo":"GitoxideLabs/gitoxide","slug":"head-changed-while-preparing-to-attach","errorCode":null,"errorMessage":"HEAD changed while preparing to attach","messagePattern":"HEAD changed while preparing to attach","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/time_travel.rs","lineNumber":509,"sourceCode":"        .context(\"attaching requires a valid HEAD pin\")?;\n    let branch = pin\n        .target\n        .try_name()\n        .context(\"the HEAD pin must point to a local branch\")?\n        .to_owned();\n    if !branch.as_bstr().starts_with(b\"refs/heads/\") {\n        anyhow::bail!(\"the HEAD pin must point to a local branch\");\n    }\n    Ok(RememberedBranch {\n        branch,\n        branch_tip: pin.id,\n    })\n}\n\nfn validate_attach(repository: &gix::Repository, head_id: ObjectId, remembered: &RememberedBranch) -> Result<()> {\n    let head = repository.head().context(\"could not read HEAD before attaching\")?;\n    if !head.is_detached() || head.id().map(gix::Id::detach) != Some(head_id) {\n        anyhow::bail!(\"HEAD changed while preparing to attach\");\n    }\n    drop(head);\n    let pin = history::all_pins(repository)?\n        .into_iter()\n        .find(history::Pin::is_head)\n        .context(\"the HEAD pin disappeared while preparing to attach\")?;\n    if pin.target.try_name() != Some(remembered.branch.as_ref()) || pin.id != remembered.branch_tip {\n        anyhow::bail!(\"the HEAD pin changed while preparing to attach\");\n    }\n    let branch_id = repository\n        .find_reference(remembered.branch.as_ref())\n        .context(\"the remembered branch disappeared while preparing to attach\")?\n        .try_id()\n        .context(\"the remembered branch must be a direct reference\")?\n        .detach();\n    if branch_id != remembered.branch_tip {\n        anyhow::bail!(\"the remembered branch changed while preparing to attach\");\n    }","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/time_travel.rs#L491-L527","documentation":"Between remembering the HEAD state and validating before the actual attach, HEAD was re-read and no longer matches: it is not detached or its commit id changed. The library throws this to avoid attaching based on stale state. It is a concurrency/staleness guard in `validate_attach`.","triggerScenarios":"Calling attach_reporting where another process (or user) moves HEAD (checkout, commit on a branch, reset) after `remembered_branch` captured `head_id` but before validation completes, so `!head.is_detached() || head.id() != Some(head_id)`.","commonSituations":"Another terminal or IDE performing checkouts concurrently; background tooling (hooks, CI agents) touching the same repo; a slow operation raced by the user switching branches.","solutions":["Ensure no other process is operating on the repository, then retry the attach.","Re-run the whole attach flow from the start so the remembered state is re-captured.","Check `git reflog` to see what moved HEAD during the operation."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in 0..3 {\n    match attach_reporting(...) {\n        Err(e) if e.to_string().contains(\"HEAD changed while preparing\") => {\n            std::thread::sleep(backoff(attempt));\n            continue; // re-capture state and retry\n        }\n        other => { other?; break; }\n    }\n}","preventionTips":["Ensure exclusive access to the repository during the attach flow.","Pause IDE auto-checkout/background git jobs while running.","Use file locks or a supervisor to serialize operations on the same repo."],"tags":["git","race-condition","concurrency","head-changed"],"backgroundTag":"invalid-state-transition","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"}