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

  1. Stage all resolved files so every index entry reaches the Unconflicted stage, then retry
  2. Re-run the conflicted step from scratch and resolve completely this time
  3. 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

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


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)