GitoxideLabs/gitoxide · error
the conflict index still has unresolved entries
Error message
the conflict index still has unresolved entries
What it means
When replaying a plan step that was previously in conflict, the library loads the saved conflict index and requires the user to have resolved every entry: all index entries must be at stage `Unconflicted`. If any entry remains at stage 1/2/3 (unmerged), the rebase refuses to build the commit from a half-resolved index.
Solutions
- Stage all resolved files so every index entry reaches the Unconflicted stage, then retry
- Re-run the conflicted step from scratch and resolve completely this time
- Inspect the conflict index entries (`entry.stage()`) to find which paths remain unresolved
Example fix
// before: resolve file on disk only fs::write(path, resolved_content)?; // after: also update the index let mut index = repo.index?; index.add_entry(repo.workdir_path(path)?)?; index.write(Default::default())?;
Defensive patterns
Strategy: try-catch
Validate before calling
fn fully_resolved(index: &gix::index::File) -> bool {
index.entries().iter().all(|e| e.stage() == gix::index::entry::Stage::Unconflicted)
} Try / catch
match result {
Err(e) if e.to_string().contains("unresolved entries") => {
eprintln!("stage every conflicted path before continuing the rebase");
}
r => r?,
} Prevention
- After editing conflicted files, always stage them (`git add`) before continuing
- Check the conflict index stage of every entry before resuming an interrupted rebase
- Avoid killing rebase tooling mid-conflict; use its abort/resume flow
When it happens
Trigger: Continuing/finishing a rebase step that had conflicts while `git add`/index updates were never run for some conflicted paths; loading a stale conflict index saved by an earlier interrupted run; resolving files on disk but not staging them.
Common situations: Users editing conflicted files in an editor, forgetting to stage; automation aborting mid-conflict-resolution and later resuming; tooling that checks out files but not into the index.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- aborted without changes: conflict while applying ; pass…
- aborted without changes: refusing to materialize a conflict…
- stopped at a materialized conflict
- could not apply conflict stages to the prepared index
- Cannot use iter_v1() on index of type
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/decac7de25ef74ef.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/rebase.rs:1735
let head = repo
.head()?
.peel_to_commit()
.context("could not resolve the conflicted HEAD commit")?;
resolved_head = Some((*planned, head.id));
let mut commit = head
.decode()
.context("could not decode the conflicted HEAD commit")?
.into_owned()
.context("could not own the conflicted HEAD commit")?;
let index = repo
.index_or_empty()
.context("could not load the resolved conflict index")?;
if index
.entries()
.iter()
.any(|entry| entry.stage() != gix::index::entry::Stage::Unconflicted)
{
anyhow::bail!("the conflict index still has unresolved entries");
}
commit.tree = super::create::index_tree(&repo, &index)?;
commit
}
PlanCommit::Empty(title) => gix::objs::Commit {
tree: parent_tree(&repo, Some(parent))?,
parents: [parent].into_iter().collect(),
author: author.clone(),
committer: committer.clone(),
encoding: None,
message: title.clone(),
extra_headers: Vec::new(),
},
};
let graph_parents = match step.commit {
PlanCommit::Pick(id) | PlanCommit::Copy(id) | PlanCommit::Resolved(id) => {
graph.parents_of(id).context("a picked commit is incomplete")?
}View on GitHub (pinned to e73179060b)