GitoxideLabs/gitoxide · warning
in restore mode a hash is set
Error message
in restore mode a hash is set
What it means
A `expect()` panic in `try_read_trailer` of the pack entry iterator. In `input::Mode::Restore` the iterator must have been constructed with a hash to restore the pack trailer; `self.hash` is `None`, meaning the mode/hash pairing invariant was violated at construction time.
Solutions
- Always supply a `gix_hash::Kind`-derived hash when using `Mode::Restore`; use `Mode::Verify` or `Mode::Ignore` otherwise
- Construct iterators through the public `iterate_from`/`new` helpers instead of internal fields
- Update gix-pack and adapt to the current Mode API
Example fix
// before let iter = BytesToEntriesIterator::new(data, Mode::Restore, None, path, id); // after let iter = BytesToEntriesIterator::new(data, Mode::Restore, Some(gix_hash::Kind::Sha1), path, id);
Defensive patterns
Strategy: validation
Validate before calling
// when constructing the iterator, only pass Mode::Restore together with a hash
let hash = if mode == input::Mode::Restore { Some(hash_kind) } else { None }; Try / catch
let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| iterator.next()));
if r.is_err() { eprintln!("Restore mode without hash"); } Prevention
- Always pair Mode::Restore with a supplied hash kind
- Prefer public constructors (`iterate_from`) over building the iterator manually
- Use Mode::Verify or Mode::Ignore when no hash is available
When it happens
Trigger: Using `gix_pack::data::input::BytesToEntriesIterator` (or `iterate_from`) with `input::Mode::Restore` where the hash was not supplied at construction — typically only via misusing internal constructors, not the public API which requires the hash for Restore mode.
Common situations: Writing custom pack streaming code that copies gix internals, or upgrading across versions where Mode constructors changed.
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
- a non-delta entry
- object kind as set by cache
- consumed bytes as set by cache
- at least one delta chain item
- a base object as root of any delta chain that we are here…
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/be08e5565d3946a4.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/data/input/bytes_to_entries.rs:190
Ok(if self.objects_left == 0 {
let mut id = gix_hash::ObjectId::null(self.object_hash);
if let Err(err) = self.read.read_exact(id.as_mut_slice())
&& self.mode != input::Mode::Restore
{
return Err(input::Error::Io(err.into()));
}
if let Some(hash) = self.hash.take() {
let actual_id = hash.try_finalize().map_err(gix_hash::io::Error::from)?;
if self.mode == input::Mode::Restore {
id = actual_id;
} else {
actual_id.verify(&id)?;
}
}
Some(id)
} else if self.mode == input::Mode::Restore {
let hash = self.hash.clone().expect("in restore mode a hash is set");
Some(hash.try_finalize().map_err(gix_hash::io::Error::from)?)
} else {
None
})
}
}
fn read_and_pass_to<R: io::Read, W: io::Write>(read: &mut R, to: W) -> PassThrough<&mut R, W> {
PassThrough { read, write: to }
}
impl<R> Iterator for BytesToEntriesIter<R>
where
R: io::BufRead,
{
type Item = Result<input::Entry, input::Error>;
fn next(&mut self) -> Option<Self::Item> {View on GitHub (pinned to e73179060b)