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

  1. Only obtain `LineRef` values from `LineRef::from_bytes`/library parsers; never construct the field directly.
  2. Ensure the reflog belongs to a repository with the hash kind you expect; do not mix SHA-1 and SHA-256 reflogs.
  3. Sanitize or regenerate corrupted reflog lines (restore from a healthy clone or delete the corrupt log file).
  4. 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

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


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)