GitoxideLabs/gitoxide · warning
a non-delta entry
Error message
a non-delta entry
What it means
This is a Rust `expect()` panic, not a recoverable error. `decode_entry` decompresses a pack entry that was matched as a non-delta kind (Tree/Blob/Commit/Tag) and then calls `entry.header.as_kind()`, which returns `None` only for delta headers. By construction this branch can only hold a non-delta header, so the expect encodes an internal invariant; failure means a logic bug in gix-pack.
Solutions
- Update gix-pack to the latest patch release in case the invariant was fixed
- Do not construct or decode pack entries with hand-modified headers; use intact packs
- If reproducible, file a bug with the pack file and the call stack
Defensive patterns
Strategy: try-catch
Try / catch
let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| pack.decode_entry(id, &mut out, ...)));
match outcome {
Ok(res) => res, // Result already conveys decode errors
Err(_) => eprintln!("gix-pack internal panic while decoding entry"),
} Prevention
- Keep gix-pack updated to released versions
- Do not decode hand-crafted or mutated pack entries
- If you see this panic, treat it as a bug and report it
When it happens
Trigger: Calling `gix_pack::data::File::decode_entry` on a non-delta entry; the panic fires only if the match arm guarding this code ever admits an `OfsDelta`/`RefDelta` header, i.e. due to a library bug or modified/internal code paths.
Common situations: Practically never hit by library users; seen during gix-pack development, when patching the decoder, or when fuzzing mutated pack files through decode_entry.
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
- cursor.is_delta() only allows deltas here
- 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/c5a5a2aebdadbcf7.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/data/file/decode/entry.rs:207
&self,
entry: data::Entry,
out: &mut Vec<u8>,
inflate: &mut gix_zlib::Inflate,
resolve: &dyn Fn(&gix_hash::oid, &mut Vec<u8>) -> Option<ResolvedBase>,
delta_cache: &mut dyn cache::DecodeEntry,
) -> Result<Outcome, Error> {
use crate::data::entry::Header::*;
match entry.header {
Tree | Blob | Commit | Tag => {
let size = self.decoded_object_size(entry.decompressed_size)?;
if let Some(additional) = size.checked_sub(out.len()) {
out.try_reserve(additional)?;
}
out.resize(size, 0);
self.decompress_entry(&entry, inflate, out.as_mut_slice())
.map(|consumed_input| {
Outcome::from_object_entry(
entry.header.as_kind().expect("a non-delta entry"),
&entry,
consumed_input,
)
})
}
OfsDelta { .. } | RefDelta { .. } => self.resolve_deltas(entry, resolve, inflate, out, delta_cache),
}
}
/// resolve: technically, this shouldn't ever be required as stored local packs don't refer to objects by id
/// that are outside of the pack. Unless, of course, the ref refers to an object within this pack, which means
/// it's very, very large as 20bytes are smaller than the corresponding MSB encoded number
fn resolve_deltas(
&self,
last: data::Entry,
resolve: &dyn Fn(&gix_hash::oid, &mut Vec<u8>) -> Option<ResolvedBase>,
inflate: &mut gix_zlib::Inflate,
out: &mut Vec<u8>,View on GitHub (pinned to e73179060b)