GitoxideLabs/gitoxide · error
only value and unspecified are possible here
Error message
only value and unspecified are possible here
What it means
This is a Rust `unreachable!()` panic in `gix-merge`'s merge-driver selection. The outer match on `attributes::StateRef` already filtered to only `Value` and `Unspecified` variants, so any other variant here indicates the enum grew new variants without updating this match — a broken internal invariant, not a user-triggerable condition.
Solutions
- Rebuild with consistent, semver-compatible versions of `gix-attributes` and `gix-merge` (run `cargo update -p gix-attributes` carefully and `cargo check`).
- Update `gix-merge` to a version matching the installed `gix-attributes` (both from the same release train).
- If you maintain the code, replace `unreachable!` with an explicit arm mapping the new variant to a driver or an error.
- Report the panic upstream with the attribute configuration that triggered the merge.
Example fix
// before
_ => unreachable!("only value and unspecified are possible here"),
// after
other => return Err(message!("unsupported attribute state {other:?} for merge driver")) Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure matching gix-merge / gix-attributes versions at build time // cargo tree -i gix-attributes // confirm a single, expected version
Try / catch
// Panics are not catchable safely in Rust; pin dependency versions.
// gix = { version = "X", exact = true } // avoid mixed gix-* versions
// Wrap merges in a subprocess (gix CLI) if panic isolation is required. Prevention
- Keep all gix-* crates on the same release version
- Run cargo update deliberately and inspect gix-attributes bumps
- Prefer catch_unwind boundaries when embedding gix in a long-running app
When it happens
Trigger: Only triggered if the `gix_attributes::StateRef` enum gains a third variant (e.g. via a dependency upgrade of `gix-attributes`) while this match is not updated; effectively impossible on a consistent build of the crate.
Common situations: Hit during a merge that consults `merge` attributes to pick a merge driver when the compiled `gix-attributes` version disagrees with the code expectations; otherwise never seen in practice.
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
- parent-match assures this
- 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/c87916fd92af66c9.
Report an issue: GitHub.
Appendix: source
Thrown at gix-merge/src/blob/platform/prepare_merge.rs:66
.map_err(|err| Error::Attributes {
source: err,
kind: ResourceKind::CurrentOrOurs,
rela_path: current.rela_path.clone(),
})?;
entry.matching_attributes(&mut self.attrs);
let mut attrs = self.attrs.iter_selected();
let merge_attr = attrs.next().expect("pre-initialized with 'merge'");
let marker_size_attr = attrs.next().expect("pre-initialized with 'conflict-marker-size'");
let mut driver = match merge_attr.assignment.state {
attributes::StateRef::Set => DriverChoice::BuiltIn(BuiltinDriver::Text),
attributes::StateRef::Unset => DriverChoice::BuiltIn(BuiltinDriver::Binary),
attributes::StateRef::Value(_) | attributes::StateRef::Unspecified => {
let name = match merge_attr.assignment.state {
attributes::StateRef::Value(name) => Some(name.as_bstr()),
attributes::StateRef::Unspecified => {
self.options.default_driver.as_ref().map(|name| name.as_bstr())
}
_ => unreachable!("only value and unspecified are possible here"),
};
self.find_driver_by_name(name)
}
};
if let attributes::StateRef::Value(value) = marker_size_attr.assignment.state
&& let Some(value) = u8::from_str(value.as_bstr().to_str_lossy().as_ref())
.ok()
.and_then(NonZeroU8::new)
{
match &mut options.text.conflict {
Conflict::Keep { marker_size, .. } => *marker_size = value,
Conflict::ResolveWithOurs | Conflict::ResolveWithTheirs | Conflict::ResolveWithUnion => {}
}
}
if let Some(recursive_driver_name) = match driver {
DriverChoice::Index(idx) => self.drivers.get(idx),
_ => None,
}View on GitHub (pinned to e73179060b)