GitoxideLabs/gitoxide · error · anyhow::Error
File conflicted
Error message
File conflicted
What it means
The file (blob) merge ended in a conflict: the requested `Resolution::Conflict` path was taken, the conflicted buffer is still written to stdout, and then the command bails with `File conflicted` to signal a non-zero exit. This is the intended way for the CLI to report a blob-level conflict.
Solutions
- Inspect the conflicted output on stdout and resolve markers manually
- Re-run with a resolution option that auto-picks a side if available
- Use a different merge driver/strategy for the blob
Example fix
// before $ gix merge file base ours theirs # exit: File conflicted // after: edit the emitted conflict markers, or choose a non-conflict resolution flag $ gix merge file base ours theirs --resolution <ours|theirs>
Defensive patterns
Strategy: try-catch
Validate before calling
// inspect the merge result before treating exit as fatal
let conflicted = output.contains("<<<<<<<");
if conflicted { eprintln!("blob merge produced conflict markers"); }
Try / catch
match result {
Err(e) if e.to_string() == "File conflicted" => {
// stdout already contains the conflicted buffer; route to manual resolution
1
}
other => { other?; 0 }
}
Prevention
- Treat non-zero exit plus stdout content as normal conflict flow, not a crash
- Pick merge drivers that suit the content type
- Check object sizes to avoid the related too-large failure path
When it happens
Trigger: Running `gix merge file` where the three-way content merge produces conflict markers and `resolution == Resolution::Conflict`; also reachable when buffers are too large (that case raises a different 'Participating object was too large' error).
Common situations: Merging versions of a file with overlapping edits; using the command as a custom merge driver in CI; reproducing `git merge-file` semantics with gitoxide.
Related errors
- Tree conflicted
- Tree conflicted, refusing to write commit
- Tree conflicted
- initial hunks are never ancestors
- we prohibit this
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/c20dfd3918c08403.
Report an issue: GitHub.
Appendix: source
Thrown at gitoxide-core/src/repository/merge/file.rs:87
Conflict::ResolveWithUnion => None,
};
}
let platform = cache.prepare_merge(&repo.objects, options)?;
let labels = gix::merge::blob::builtin_driver::text::Labels {
ancestor: Some(base.as_ref()),
current: Some(ours.as_ref()),
other: Some(theirs.as_ref()),
};
let mut buf = repo.empty_reusable_buffer();
let (pick, resolution) = platform.merge(&mut buf, labels, &repo.command_context()?)?;
let buf = platform
.buffer_by_pick(pick)
.map_err(|_| anyhow!("Participating object was too large"))?
.unwrap_or(&buf);
out.write_all(buf)?;
if resolution == Resolution::Conflict {
bail!("File conflicted")
}
Ok(())
}
fn worktree_roots(
base: Option<gix::Id<'_>>,
ours: Option<gix::Id<'_>>,
theirs: Option<gix::Id<'_>>,
workdir: Option<&Path>,
) -> anyhow::Result<gix::merge::blob::pipeline::WorktreeRoots> {
let roots = if base.is_none() || ours.is_none() || theirs.is_none() {
let workdir = workdir.context("A workdir is required if one of the bases are provided as path.")?;
gix::merge::blob::pipeline::WorktreeRoots {
current_root: ours.is_none().then(|| workdir.to_owned()),
other_root: theirs.is_none().then(|| workdir.to_owned()),
common_ancestor_root: base.is_none().then(|| workdir.to_owned()),
}
} else {View on GitHub (pinned to e73179060b)