{"record":{"id":"8f1068d4c88a3b58","repo":"GitoxideLabs/gitoxide","slug":"a-rebase-plan-contains-an-invalid-or-duplicate-pic","errorCode":null,"errorMessage":"a rebase plan contains an invalid or duplicate pick","messagePattern":"a rebase plan contains an invalid or duplicate pick","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/rebase.rs","lineNumber":1652,"sourceCode":"        .to_owned()\n        .context(\"could not own the Git committer\")?;\n    repo = repo.with_object_memory();\n\n    let scope: HashSet<_> = plan.scope.iter().copied().collect();\n    let mut picked = HashSet::new();\n    for step in &plan.steps {\n        if let PlanCommit::Copy(id) = step.commit\n            && graph.parents_of(id).context(\"a copied commit is incomplete\")?.len() != 1\n        {\n            anyhow::bail!(\"copying a commit requires it to have exactly one parent\");\n        }\n        let ids = match step.commit {\n            PlanCommit::Pick(id) | PlanCommit::Resolved(id) => Some(id).into_iter().chain(step.squash.iter().copied()),\n            PlanCommit::Copy(_) | PlanCommit::Empty(_) => None.into_iter().chain(step.squash.iter().copied()),\n        };\n        for id in ids {\n            if !scope.contains(&id) || !picked.insert(id) {\n                anyhow::bail!(\"a rebase plan contains an invalid or duplicate pick\");\n            }\n            if graph.parents_of(id).context(\"a picked commit is incomplete\")?.len() > 1 {\n                anyhow::bail!(\"merge commits cannot be picked by the rebase editor\");\n            }\n        }\n    }\n\n    let checkout_target = if repo.workdir().is_some() {\n        plan.checkout\n            .as_ref()\n            .map(|checkout| checkout.target)\n            .or(infer_plan_checkout(&repo, graph, &plan)?)\n    } else {\n        None\n    };\n    if plan.checkout.is_none()\n        && checkout_target.is_some()\n        && !plan","sourceCodeStart":1634,"sourceCodeEnd":1670,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/rebase.rs#L1634-L1670","documentation":"The rebase-plan validator requires every pick/squash id to (a) belong to the plan's declared scope and (b) appear at most once across all steps. A duplicate pick or an id outside the scope would produce an inconsistent rewrite, so the plan is rejected.","triggerScenarios":"A plan whose steps reference commit ids not in `plan.scope`; the same commit id picked twice (e.g. once as Pick and once inside a squash list); tooling that appends steps without deduplicating ids.","commonSituations":"Auto-generated plans that repeat a commit because it appears in two ranges; stale plans replayed after history changed so ids fell out of scope; hand-edited todo files with duplicated lines.","solutions":["Deduplicate commit ids across all plan steps before submitting","Ensure every picked id is included in `plan.scope`","Regenerate the plan from the current history instead of replaying a stale one"],"exampleFix":"// before\nsteps.push(pick(a)); steps.push(pick(a)); // duplicate\n// after\nlet mut seen = HashSet::new();\nif seen.insert(a) { steps.push(pick(a)); }","handlingStrategy":"validation","validationCode":"fn validate_picks(scope: &HashSet<ObjectId>, picks: &[ObjectId]) -> bool {\n    let mut seen = HashSet::new();\n    picks.iter().all(|p| scope.contains(p) && seen.insert(*p))\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"invalid or duplicate pick\") => {\n        eprintln!(\"deduplicate picks and ensure all are in plan scope\");\n    }\n    r => r?,\n}","preventionTips":["Deduplicate ids across all steps before submitting a plan","Regenerate plans after history changes instead of replaying stale ones","Assert scope coverage in plan builders"],"tags":["rebase","duplicate","plan-validation"],"backgroundTag":"invalid-argument-value","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"}