GitoxideLabs/gitoxide · info

peeked value exists

Error message

peeked value exists

What it means

In `OverlayIter::next`, the packed iterator was `peek`ed and returned `Some`, so the following `next()` must also return `Some`; `expect("peeked value exists")` enforces that. A panic indicates the underlying packed-refs iterator misbehaved (peek and next disagree) or the iterator was mutated concurrently.

Solutions

  1. Ensure the iterator is not shared or mutated across threads (wrap in a Mutex if needed)
  2. Re-run the iteration from a fresh `store.iter()`; a transient state may explain it
  3. Verify `packed-refs` integrity and regenerate it (e.g. `git pack-refs --all`)
  4. If reproducible on a fresh iterator, report a gix-ref bug with the packed-refs contents
Defensive patterns

Strategy: retry

Try / catch

// Wrap iteration in retry against a fresh iterator
for _ in 0..3 { if let Ok(refs) = std::panic::catch_unwind(|| store.iter().collect::<Vec<_>>()) { break; } }

Prevention

When it happens

Trigger: Iterating references over a repository with a `packed-refs` file where `Peekable::peek` succeeded but the subsequent `next()` returned `None` — only possible with a broken/concurrently-modified iterator implementation.

Common situations: Effectively unreachable; if observed, suspect concurrent modification of the iterator, custom unsafe wrapper code, or a gix-ref/packed-refs bug. Normal single-threaded iteration of `store.iter()` never triggers it.

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


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/0d2b08450b5b84e5. Report an issue: GitHub.

Appendix: source

Thrown at gix-ref/src/store/file/overlay_iter.rs:161

                    (Some(r_gitdir @ Ok((_, git_dir_name))), Some(r_cd @ Ok((_, common_dir_name)))) => {
                        match git_dir_name.cmp(common_dir_name) {
                            Ordering::Less => Some((r_gitdir, IterKind::Git)),
                            Ordering::Equal => Some((r_gitdir, IterKind::GitAndConsumeCommon)),
                            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");

View on GitHub (pinned to e73179060b)