GitoxideLabs/gitoxide · info
prior peek
Error message
prior peek
What it means
Same `next()` merge logic: after `peek_loose` returned `Some`, the loose iterator's `next()` must also return `Some`; `expect("prior peek")` enforces that the previously peeked loose entry still exists. A panic means peek and next disagreed for the loose iterator (git-dir or common-dir).
Solutions
- Avoid mutating refs (or running gc) concurrently with reference iteration, or hold appropriate locking
- Re-run the iteration; a one-off race resolves itself
- Check for background processes touching `.git/refs` during the operation
- If reproducible without concurrency, report a gix-ref bug
Defensive patterns
Strategy: retry
Try / catch
// Retry the whole iteration on panic, assuming a transient race let refs = (0..3).find_map(|_| std::panic::catch_unwind(|| store.iter().collect::<Vec<_>>()).ok());
Prevention
- Don't run gc/ref-deletion concurrently with ref iteration
- Serialize ref access with locking in multi-process tooling
- Detect ref-database churn (mtimes under refs/) and retry
- Report single-threaded reproductions as gix-ref bugs
When it happens
Trigger: Enumerating loose refs where `peek_loose` observed an entry but the inner `loose_iter(kind).next()` then returned `None` — caused by concurrent deletion of loose ref files between peek and next, or a broken iterator.
Common situations: Most plausible real-world cause is another process (e.g. `git gc`, a concurrent ref update) deleting the loose ref while the iteration was in progress; otherwise a gix-ref bug.
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
- caller knows there is a common iter
- one of our bases contains the path
- peeked value exists
- name retrieval configured
- BUG: packed refs cannot contain symbolic refs, catch that…
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/9509dda2b4e142cc.
Report an issue: GitHub.
Appendix: source
Thrown at gix-ref/src/store/file/overlay_iter.rs:165
Ordering::Greater => Some((r_cd, IterKind::Common)),
}
}
},
None => git_dir.peek().map(|r| (r, IterKind::Git)),
}
}
match self.iter_packed.as_mut() {
Some(packed_iter) => match (
peek_loose(&mut self.iter_git_dir, self.iter_common_dir.as_mut()),
packed_iter.peek(),
) {
(None, None) => None,
(None, Some(_)) | (Some(_), Some(Err(_))) => {
let res = packed_iter.next().expect("peeked value exists");
Some(self.convert_packed(res))
}
(Some((_, kind)), None) | (Some((Err(_), kind)), Some(_)) => {
let res = self.loose_iter(kind).next().expect("prior peek");
Some(self.convert_loose(res))
}
(Some((Ok((_, loose_name)), kind)), Some(Ok(packed))) => match loose_name.as_ref().cmp(packed.name) {
Ordering::Less => {
let res = self.loose_iter(kind).next().expect("prior peek");
Some(self.convert_loose(res))
}
Ordering::Equal => {
drop(packed_iter.next());
let res = self.loose_iter(kind).next().expect("prior peek");
Some(self.convert_loose(res))
}
Ordering::Greater => {
let res = packed_iter.next().expect("name retrieval configured");
Some(self.convert_packed(res))
}
},
},View on GitHub (pinned to e73179060b)