GitoxideLabs/gitoxide · error

could not apply conflict stages to the prepared index

Error message

could not apply conflict stages to the prepared index

What it means

When a tix edit produces a conflict, the code rebuilds a tree representing the conflicted state by writing conflict stages into a prepared index via `gix::merge::tree::apply_index_entries`. That function returns success only if all stages could be applied consistently; on failure tix bails because it cannot materialize a faithful conflicted index/tree for the user.

Solutions

  1. Retry the edit; if it recurs, resolve the conflict manually in a normal rebase instead of via the interactive edit.
  2. Avoid editing histories whose conflicts involve type changes or rename/rename cases; resolve those first with plain git.
  3. Inspect the conflict entry set (stages/modes) feeding `apply_index_entries`; if a tix bug, report with a minimal reproduction repository.
Defensive patterns

Strategy: try-catch

Try / catch

// Rust: fall back to a plain rebase when conflict materialization fails
match edit_result {
    Err(e) if e.to_string().contains("could not apply conflict stages") => {
        eprintln!("falling back to manual conflict resolution");
    }
    other => other?,
}

Prevention

When it happens

Trigger: `apply_index_entries` returning `false` while constructing the conflict tree: the recorded conflict entries are inconsistent with the index (missing stages, mismatched modes/paths, or removals that cannot be pruned under `RemovalMode::Prune`).

Common situations: Conflicts involving type changes or delete/modify combinations that the conflict-application routine cannot represent; conflicts on paths already removed from the prepared index; unusual merge scenarios (rename/rename) producing stage sets the function rejects.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/8763a97f4534e5bf. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/rebase.rs:354

}

impl PersistedConflict {
    pub(crate) fn map(&self, id: ObjectId) -> Option<ObjectId> {
        self.rewritten.get(&id).copied().unwrap_or(Some(id))
    }

    pub(crate) fn materialize(&mut self) -> Result<()> {
        let mut index = self
            .repo
            .index_from_tree(&self.merged_tree)
            .context("could not prepare the conflicting index")?;
        if !gix::merge::tree::apply_index_entries(
            &self.conflicts,
            gix::merge::tree::TreatAsUnresolved::git(),
            &mut index,
            gix::merge::tree::apply_index_entries::RemovalMode::Prune,
        ) {
            anyhow::bail!("could not apply conflict stages to the prepared index");
        }
        index.remove_tree();
        let ours_tree = self
            .repo
            .find_commit(self.commit)
            .context("could not find the conflicting commit")?
            .tree_id()
            .context("could not read the conflicting commit tree")?
            .detach();
        let workdir = self
            .repo
            .workdir()
            .context("materializing a conflict requires a worktree")?;
        super::forget::apply_tree_transition(workdir, ours_tree, self.merged_tree)
            .context("could not check out the conflicting merge result")?;
        if let Err(err) = index
            .write(gix::index::write::Options::default())
            .context("could not write the conflicting index")

View on GitHub (pinned to e73179060b)