GitoxideLabs/gitoxide · error
parent-match assures this
Error message
parent-match assures this
What it means
This `unreachable!()` in `gix-merge`'s three-way tree merge fires when a conflict-side change is neither a Modification nor a Deletion while applying an ours-changed/theirs-deleted resolution. The enclosing code assumes the parent matching logic guarantees only those two `Change` shapes can occur here.
Solutions
- Report the panic upstream with the two trees and ancestor that reproduce the merge.
- Update `gix-merge` to the latest patch version in case the parent-matching invariant was fixed.
- If you maintain the code, replace the wildcard arm with an explicit error or handle `Change::Addition` deliberately.
Example fix
// before
_ => unreachable!("parent-match assures this"),
// after
other => return Err(message!("unexpected change {other:?} during ours-modified/theirs-deleted resolution")) Defensive patterns
Strategy: try-catch
Validate before calling
// Validate inputs are complete trees before merging // gix_merge::tree(...) requires ancestor, ours, theirs tree objects resolvable in the object store
Try / catch
// Panics propagate; run merges behind catch_unwind or in a worker process. let result = std::panic::catch_unwind(|| gix_merge::tree(...));
Prevention
- Use the same version for all gix-* crates
- Test merges with tricky directory-add/delete pairs before deploying
- Report upstream panics with reproducing trees
When it happens
Trigger: Calling `gix_merge::tree(...)` (merge) with an index or tree state where a change entry for the current location is `Addition` instead of Modification/Deletion — i.e. a broken parent-child correspondence between merged trees.
Common situations: Practically unreachable; would indicate a bug in the change enumeration during a merge involving deeply nested paths where one side deleted a directory.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- only value and unspecified are possible here
- upper match already assured we only deal with blobs
- fixed size array with three items
- internal nodes have no object ID key
- the matching node was checked to be a subtree
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/ffbd613416751d5c.
Report an issue: GitHub.
Appendix: source
Thrown at gix-merge/src/tree/function/resolve.rs:1070
];
match resolve_tree_conflicts {
None => {
editor.upsert(toc(location), entry_mode.kind(), *id)?;
}
Some(ResolveWith::Ours) => {
let ours = match outer_side {
Original => ours,
Swapped => theirs,
};
match ours {
Change::Modification { .. } => {
editor.upsert(toc(location), entry_mode.kind(), *id)?;
}
Change::Deletion { .. } => {
editor.remove(toc(location))?;
}
_ => unreachable!("parent-match assures this"),
}
}
Some(ResolveWith::Ancestor) => {}
}
should_fail_on_conflict(Conflict::without_resolution(
ResolutionFailure::OursModifiedTheirsDeleted,
(ours, theirs, side, outer_side),
entries,
))
};
let deletion_was_applied = match resolve_tree_conflicts {
None => deletion_replaced_by_directory,
Some(ResolveWith::Ours) => side.to_global(outer_side).is_swapped(),
Some(ResolveWith::Ancestor) => false,
};
if deletion_was_applied {
match side {
Original => theirs_disposition = ChangeDisposition::Applied,View on GitHub (pinned to e73179060b)