GitoxideLabs/gitoxide · warning
parse validation
Error message
parse validation
What it means
A Rust `expect()` panic in `LineRef::previous_oid()` (gix-ref/store/file/log/line.rs). Reflog lines store the old object id as fixed-width hex; the line parser (`LineRef::from_bytes`) already verified the hex digits and length before constructing `LineRef`, so `ObjectId::from_hex` must succeed. A panic means hex bytes reached this accessor that the parser never validated — i.e. the `LineRef` was built through `from_bytes`-bypassing paths or on data with a hash length mismatch.
Solutions
- Only obtain `LineRef` values from `LineRef::from_bytes`/library parsers; never construct the field directly.
- Ensure the reflog belongs to a repository with the hash kind you expect; do not mix SHA-1 and SHA-256 reflogs.
- Sanitize or regenerate corrupted reflog lines (restore from a healthy clone or delete the corrupt log file).
- Report upstream if library-parsed lines panic — internal invariant violation.
Example fix
// before
let line = LineRef { previous_oid: b"zzzz".as_ref().into(), .. };
line.previous_oid(); // panics
// after
let line = LineRef::from_bytes(raw_log_line)?; // validates hex first
let old_id = line.previous_oid(); Defensive patterns
Strategy: validation
Validate before calling
// ensure line came from the parser before reading ids let line = gix_ref::store::file::log::LineRef::from_bytes(raw)?; // validates hex
Prevention
- Only use LineRef produced by from_bytes/owned Line conversion
- Match hash kind to the reflog's repository
- Never hand-edit reflog files
When it happens
Trigger: Calling `previous_oid()` on a `LineRef` whose `previous_oid` field came from bytes not parsed by `LineRef::from_bytes` (e.g. constructed directly/unsafely), or parsing lines with a hash kind shorter/longer than the hex actually present.
Common situations: Hand-editing or synthesizing reflog entries; parsing reflog files written for a different hash algorithm (SHA-256 vs SHA-1); wrapping raw byte slices as `LineRef` in tests or FFI.
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
- BUG: Invalid state: we never discard only our file, always…
- we are called from a valid ref
- parser validation
- we have read non-zero bytes before
- prior validation
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/3d716728c597f39b.
Report an issue: GitHub.
Appendix: source
Thrown at gix-ref/src/store/file/log/line.rs:54
write!(out, "{} {} ", self.previous_oid, self.new_oid)?;
self.signature.write_to(out)?;
writeln!(out, "\t{}", check_newlines(self.message.as_ref())?)
}
}
fn check_newlines(input: &BStr) -> Result<&BStr, Error> {
if input.find_byte(b'\n').is_some() {
return Err(Error::IllegalCharacter);
}
Ok(input)
}
}
impl LineRef<'_> {
/// The previous object id of the ref. It will be a null hash if there was no previous id as
/// this ref is being created.
pub fn previous_oid(&self) -> ObjectId {
ObjectId::from_hex(self.previous_oid).expect("parse validation")
}
/// The new object id of the ref, or a null hash if it is removed.
pub fn new_oid(&self) -> ObjectId {
ObjectId::from_hex(self.new_oid).expect("parse validation")
}
}
impl<'a> From<LineRef<'a>> for Line {
fn from(v: LineRef<'a>) -> Self {
Line {
previous_oid: v.previous_oid(),
new_oid: v.new_oid(),
signature: v.signature.into(),
message: v.message.into(),
}
}
}
View on GitHub (pinned to e73179060b)