GitoxideLabs/gitoxide · warning
consumed bytes as set by cache
Error message
consumed bytes as set by cache
What it means
A `expect()` panic in `resolve_deltas` for `consumed_input`. In the cache-hit path (empty delta chain), the number of input bytes consumed by the cached entry must have been recorded by the cache along with the entry. `None` means the cache stored data without consumption metadata, breaking the cache/decoder contract.
Solutions
- Use the stock delta cache implementations which always record consumed input
- Verify any custom `gix_pack::cache::FromEntries` implementation sets kind and consumed_input when storing entries
- Update gix-pack and report a reproducible case upstream
Defensive patterns
Strategy: validation
Validate before calling
// ensure your custom cache always records consumed input when storing entries
// if let Some(entry) = my_cache.get(id, offset) { assert!(entry.consumed_input.is_some()); } Try / catch
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| pack.decode_entry(id, &mut out, ...))).is_err()
Prevention
- Prefer built-in cache types over custom ones
- Test any custom cache against gix-pack's test suite
- Update gix-pack regularly
When it happens
Trigger: Same as the sibling `object_kind` expect: `decode_entry` on a delta entry fully served by a delta cache that kept the first entry but allegedly did not record consumed input bytes.
Common situations: Seen only during gix-pack development, fuzzing, or if a custom `cache::FromEntries` implementation is supplied that fails to set consumed_input.
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
- object kind as set by cache
- last seen won't lie
- a non-delta entry
- 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/a4b7c2759e7a9097.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/data/file/decode/entry.rs:299
Some(ResolvedBase::InPack(entry)) => entry,
Some(ResolvedBase::OutOfPack { end, kind }) => {
base_buffer_size = Some(end);
object_kind = Some(kind);
break;
}
None => return Err(Error::DeltaBaseUnresolved(base_id)),
},
_ => unreachable!("cursor.is_delta() only allows deltas here"),
};
}
// This can happen if the cache held the first entry itself
// We will just treat it as an object then, even though it's technically incorrect.
if chain.is_empty() {
return Ok(Outcome::from_object_entry(
object_kind.expect("object kind as set by cache"),
&first_entry,
consumed_input.expect("consumed bytes as set by cache"),
));
}
// First pass will decompress all delta data and keep it in our output buffer
// [<possibly resolved base object>]<delta-1..delta-n>...
// so that we can find the biggest result size.
let total_delta_data_size: usize = total_delta_data_size.try_into().map_err(|_| Error::OutOfMemory)?;
let chain_len = chain.len();
let actual_base_size = match base_buffer_size {
Some(size) => size,
None => self.decoded_object_size(cursor.decompressed_size)?,
};
let (first_buffer_end, second_buffer_end) = {
let delta_start = base_buffer_size.unwrap_or(0);
let delta_range = Range {
start: delta_start,View on GitHub (pinned to e73179060b)