GitoxideLabs/gitoxide · error

stopped at a materialized conflict

Error message

{operation} stopped at a materialized conflict

What it means

This is the expected stop signal after a conflict was successfully materialized: conflict markers were written to the chosen destination, objects persisted, and a continuation plan produced. The command exits with an error status so automation notices that the rebase did not finish, and prints the `tix rebase apply` command to continue.

Solutions

  1. Treat this exit as 'work saved, awaiting continuation', not a crash
  2. Follow the printed instruction: run `tix rebase apply <destination>` after resolving the markers
  3. In automation, match on this message to branch into the continuation step

Example fix

// before
set -e; tix rebase apply plan --materialize-conflicts c.txt; echo done
// after
tix rebase apply plan --materialize-conflicts c.txt || { grep -q 'stopped at a materialized conflict' log && tix rebase apply c.txt; }
Defensive patterns

Strategy: try-catch

Try / catch

let status = Command::new("tix").args(["rebase", "apply", plan]).status()?;
if !status.success() {
    // expected after materialization: resolve markers, then continue
    resolve_markers("conflicts.txt")?;
    Command::new("tix").args(["rebase", "apply", "conflicts.txt"]).status()?;
}

Prevention

When it happens

Trigger: handle_plan_conflict completes persist_objects/continuation_plan and prints the notice, then bails to terminate the current process after `--materialize-conflicts` was used and a conflict actually occurred.

Common situations: Materializing a rebase conflict to hand resolution to a human or tool; CI pipelines that must detect the stopped state; wrappers forgetting that a non-zero exit here is normal post-materialization behavior.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


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

Appendix: source

Thrown at gix-tix/src/command/rebase.rs:312

    let (notice, _, ref_rewrites, ref_changes) = match materialized {
        Ok(materialized) => materialized,
        Err(err) => {
            if destination != Path::new("-") {
                let _ = std::fs::remove_file(destination);
            }
            return Err(err);
        }
    };
    if destination == Path::new("-") {
        for line in super::ref_rewrite_lines(repo, &ref_rewrites)? {
            eprintln!("{line}");
        }
    } else {
        super::print_ref_rewrites(repo, &ref_rewrites)?;
    }
    super::record_undo(repo, "materialize rebase conflict", Ok(ref_changes));
    eprintln!("{notice}; continue with `tix rebase apply {}`", destination.display());
    anyhow::bail!("{operation} stopped at a materialized conflict")
}

fn mapped_revisions(tips: &[ObjectId], mut map: impl FnMut(ObjectId) -> Option<ObjectId>) -> Vec<OsString> {
    tips.iter()
        .filter_map(|id| map(*id))
        .map(|id| OsString::from(id.to_string()))
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::process::Command;

    fn repository() -> gix_testtools::Result<(gix_testtools::tempfile::TempDir, gix::Repository)> {
        let fixture = gix_testtools::scripted_fixture_writable("rebase_edit.sh")?;
        let repo = crate::test_repository::open_with(
            fixture.path(),

View on GitHub (pinned to e73179060b)