GitoxideLabs/gitoxide · info
io::sink() to never fail
Error message
io::sink() to never fail
What it means
`Entry::header::size()` computes a pack entry header length by writing to `io::sink()`, which can never fail; any error from `write_to` would indicate a bug, so it `.expect()`s success. Users see this panic only if `write_to` unexpectedly errors, i.e. an internal invariant broken (e.g. a size that cannot be encoded).
Solutions
- Report upstream with the decompressed_size value that triggered it
- Use `checked_*` / `Entry::header_size()` on decoded entries as a safer alternative
- Upgrade to the latest gitoxide version in case the bug is already fixed
Example fix
// before let sz = header::Entry::Base.size(size); // panics on internal bug // after let mut buf = Vec::new(); let sz = header.write_to(size, &mut buf)?; // propagate any error instead of panicking
Defensive patterns
Strategy: try-catch
Try / catch
let size = std::panic::catch_unwind(|| header::Entry::Base.size(decompressed_size)).unwrap_or(0);
Prevention
- Prefer `data::Entry::header_size()` on decoded entries in production paths
- Keep gitoxide updated; this panic indicates a library bug, not user error
- File an upstream issue with reproducing input if ever observed
When it happens
Trigger: Calling `gix_pack::data::entry::header::Entry::size(decompressed_size)` — panics only if the internal LEB64 encoder fails, which should be impossible for valid u64 sizes.
Common situations: Practically never hit in the field; encountered only during development, fuzzing, or after library modifications.
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
- Cannot use iter_v1() on index of type
- Cannot use iter_v2() on index of type
- must have been resolved
- counts were resolved beforehand
- BUG: no other error type is possible
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/b733356388258f91.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/data/entry/header.rs:120
let mut buf = [0u8; 10];
let buf = leb64_encode(*base_distance, &mut buf);
out.write_all(buf)?;
written += buf.len();
}
Blob | Tree | Commit | Tag => {}
}
Ok(written)
}
/// The size of the header in bytes when written in canonical form.
///
/// This is the number of bytes [`Self::write_to()`] would emit for `decompressed_size`.
/// It does not inspect existing pack bytes and therefore does not preserve non-canonical
/// overlong size encodings. Use [`data::Entry::header_size()`] for decoded entries when the
/// result has to match the header length present in the pack.
pub fn size(&self, decompressed_size: u64) -> usize {
self.write_to(decompressed_size, &mut io::sink())
.expect("io::sink() to never fail")
}
}
#[inline]
fn leb64_encode(mut n: u64, buf: &mut [u8; 10]) -> &[u8] {
let mut bytes_written = 1;
buf[buf.len() - 1] = n as u8 & 0b0111_1111;
for out in buf.iter_mut().rev().skip(1) {
n >>= 7;
if n == 0 {
break;
}
n -= 1;
*out = 0b1000_0000 | (n as u8 & 0b0111_1111);
bytes_written += 1;
}
debug_assert_eq!(n, 0, "BUG: buffer must be large enough to hold a 64 bit integer");
&buf[buf.len() - bytes_written..]View on GitHub (pinned to e73179060b)