{"record":{"id":"2ee424076931f105","repo":"GitoxideLabs/gitoxide","slug":"the-rebase-state-contains-duplicate-refs","errorCode":null,"errorMessage":"the rebase state contains duplicate refs","messagePattern":"the rebase state contains duplicate refs","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/todo.rs","lineNumber":790,"sourceCode":"}\n\nfn validate_state(repo: &gix::Repository, state: &State) -> Result<()> {\n    repo.find_commit(state.base)\n        .context(\"could not find the recorded rebase base\")?;\n    repo.find_commit(state.onto)\n        .context(\"could not find the recorded rebase target\")?;\n    let scope: HashSet<_> = state.scope.iter().copied().collect();\n    let continuation_sources: HashSet<_> = state.continuation_sources.iter().copied().collect();\n    if scope.len() != state.scope.len() {\n        anyhow::bail!(\"the rebase state contains duplicate scope commits\");\n    }\n    if state.tips.iter().copied().collect::<HashSet<_>>().len() != state.tips.len() {\n        anyhow::bail!(\"the rebase state contains duplicate tips\");\n    }\n    let mut refs = HashSet::new();\n    for reference in &state.expected_refs {\n        if !refs.insert(reference.name.as_bstr()) {\n            anyhow::bail!(\"the rebase state contains duplicate refs\");\n        }\n        if !scope.contains(&reference.target) && reference.target != state.base && reference.target != state.onto {\n            anyhow::bail!(\"a captured ref does not logically point into the rebase scope\");\n        }\n    }\n    if let Some(name) = &state.head_ref\n        && !state\n            .expected_refs\n            .iter()\n            .any(|reference| reference.editable && reference.name == *name)\n    {\n        anyhow::bail!(\"the recorded HEAD ref is not editable\");\n    }\n    for tip in &state.tips {\n        repo.find_commit(*tip).context(\"could not find a recorded rebase tip\")?;\n    }\n    for id in &state.scope {\n        let commit = repo","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/todo.rs#L772-L808","documentation":"`validate_state` inserts every `expected_refs[].name` into a `HashSet` of ref names; if insertion fails, two captured refs share the same fully-qualified name. Since each expected ref entry describes a distinct reference update, duplicate names are ambiguous and validation aborts.","triggerScenarios":"`parse_state` (via validate_state, gix-tix/src/edit/todo.rs:790) parses a state file where two `ref` lines (or an edit-ref/expected-ref combination) produce entries with identical `FullName`s.","commonSituations":"Hand-edited ref lists; scripts writing one `ref` line per change instead of updating the existing entry; state files merged from divergent sessions.","solutions":["Merge or remove duplicate `ref` lines so each fully-qualified ref name appears exactly once.","Regenerate the state by restarting the rebase/edit operation.","Ensure automation keys ref entries by name and updates in place rather than appending."],"exampleFix":"// before (state file)\nref aaa fast-forward \"refs/heads/wip\"\nref bbb fast-forward \"refs/heads/wip\"\n// after\nref bbb fast-forward \"refs/heads/wip\"","handlingStrategy":"validation","validationCode":"fn ref_lines_are_unique(text: &str) -> bool {\n    let names: Vec<&str> = text.lines()\n        .filter(|l| l.starts_with(\"ref \"))\n        .map(|l| l.rsplit_once(' ').map(|(_, n)| n).unwrap_or(\"\"))\n        .collect();\n    names.iter().collect::<std::collections::HashSet<_>>().len() == names.len()\n}","typeGuard":null,"tryCatchPattern":"match todo::parse(state_text) {\n    Ok(state) => apply(state),\n    Err(e) if e.to_string().contains(\"duplicate refs\") => {\n        eprintln!(\"merge duplicate ref entries; each ref name may appear once\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Key captured-ref records by fully-qualified ref name and update in place.","Validate uniqueness of ref names before writing the state file.","Round-trip validate generated state in automation before consuming it."],"tags":["rebase","state-validation","duplicate-entries","git"],"backgroundTag":"schema-validation-failed","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}