GitoxideLabs/gitoxide · error
next
Error message
next
What it means
Panic raised by `refs_sorted.next().expect("next")` in the packed-refs transaction commit loop. `peek()` had just returned `Some(Err(_))`, so `next()` must also return `Some`; if not, the peekable iterator's state contradicts itself — an internal invariant. The immediate `expect_err` converts the item into the iteration error reported to the caller.
Solutions
- Treat any occurrence as a gitoxide bug and report it with the stack trace and packed-refs contents.
- If the underlying cause is an iteration error, repair the corrupt packed-refs file.
- Use a gix-ref version without the faulty peek/next interplay.
Defensive patterns
Strategy: validation
Validate before calling
// pre-validate packed-refs parses cleanly to avoid the iteration-error path
for r in buffer.iter() { r.map_err(|e| format!("corrupt packed-refs: {e}"))?; } Try / catch
// wrap the transaction in catch_unwind at a boundary if input is untrusted let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| tx.commit()));
Prevention
- Validate the packed-refs file before running packed transactions on it.
- Report any panic in the commit loop as a gitoxide bug.
- Keep gix-ref updated to benefit from iterator-handling fixes.
When it happens
Trigger: Reaching the `(Some(Err(_)), _)` match arm during `commit()` where the peeked iteration error disappears on `next()` — logically impossible with `std::iter::Peekable`; only a bug (e.g. misuse of the iterator between peek and next) could trigger it.
Common situations: Not user-reachable under correct library use; it surfaces only when a packed-refs iteration error occurs (corrupt file) AND an internal iterator invariant is already broken.
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
- peeked value exists
- name retrieval configured
- peeled ref
- visit_non_tree() called us
- BUG: ResolvedSignatures don't exist here when nothing is set
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/f5da14251c3dd4be.
Report an issue: GitHub.
Appendix: source
Thrown at gix-ref/src/store/packed/transaction.rs:181
let mut file = self.lock.expect("a write lock for applying changes");
let refs_sorted: Box<dyn Iterator<Item = Result<packed::Reference<'_>, packed::iter::Error>>> =
match self.buffer.as_ref() {
Some(buffer) => Box::new(buffer.iter()?),
None => Box::new(std::iter::empty()),
};
let mut refs_sorted = refs_sorted.peekable();
edits.sort_by(|l, r| l.inner.name.as_bstr().cmp(r.inner.name.as_bstr()));
let mut peekable_sorted_edits = edits.iter().peekable();
file.with_mut(|f| f.write_all(HEADER_LINE))?;
let mut num_written_lines = 0;
loop {
match (refs_sorted.peek(), peekable_sorted_edits.peek()) {
(Some(Err(_)), _) => {
let err = refs_sorted.next().expect("next").expect_err("err");
return Err(commit::Error::Iteration(err));
}
(None, None) => {
break;
}
(Some(Ok(_)), None) => {
let pref = refs_sorted.next().expect("next").expect("no err");
num_written_lines += 1;
file.with_mut(|out| write_packed_ref(out, pref))?;
}
(Some(Ok(pref)), Some(edit)) => {
use std::cmp::Ordering::*;
match pref.name.as_bstr().cmp(edit.inner.name.as_bstr()) {
Less => {
let pref = refs_sorted.next().expect("next").expect("valid");
num_written_lines += 1;
file.with_mut(|out| write_packed_ref(out, pref))?;
}View on GitHub (pinned to e73179060b)