GitoxideLabs/gitoxide · error

BUG: Invalid state: we never discard only our file, always…

Error message

BUG: Invalid state: we never discard only our file, always both.

What it means

An `unreachable!()` panic in gix-ref's packed+loose reflog iterator `next()` (`store/file/log/iter`). The iterator walks two sources (own-file and packed reflog) in lockstep and asserts it never reaches the state `(Some(_), None)` — having only the own-file entry while the packed side is exhausted — because both files are discarded together during iteration. The panic fires if that invariant breaks.

Solutions

  1. Restore reflog consistency: run `git reflog` / `git fsck` with real git, or delete the affected reflog files (`rm -rf .git/logs/<ref>`) so they can be rebuilt
  2. Re-clone or re-pack the repository if reflog history is disposable (`git clone --mirror` + fresh fetch)
  3. Upgrade gix / gix-ref and retry; report the repository layout that triggered it upstream
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
fn reflog_files_consistent(git_dir: &Path, ref_name: &str) -> bool {
    let loose = git_dir.join("logs").join(ref_name);
    loose.exists() // if loose reflog exists, packed side is derived automatically; manual deletion of one side is the risk
}

Try / catch

std::panic::catch_unwind(|| iter.collect::<Vec<_>>())
    .map_err(|_| "reflog iteration hit inconsistent storage; rebuild reflogs")?

Prevention

When it happens

Trigger: Iterating a reflog (e.g. `repo.reflog()` or reflog-based history traversal) over a repository where the loose reflog file and the packed-refs reflog are out of sync in a way the iterator didn't anticipate — e.g. manually deleted or partially compacted files under `.git/logs/`, or a gix-ref iteration bug.

Common situations: Repositories maintained by mixed tooling (git gc/repack interleaved with gix, manual cleanup of `.git/logs`), corrupted or hand-edited reflog storage, or fresh gix versions with iterator regressions.

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/a7fafb76c93f7bed. Report an issue: GitHub.

Appendix: source

Thrown at gix-ref/src/store/file/log/iter.rs:240

                            .into()));
                        }
                        let n = (last_read_pos - npos) as usize;
                        self.buf.copy_within(0..end, n);
                        if let Err(err) = read.seek(std::io::SeekFrom::Start(npos)) {
                            return Some(Err(err.into()));
                        }
                        if let Err(err) = read.read_exact(&mut self.buf[..n]) {
                            return Some(Err(err.into()));
                        }
                        self.read_and_pos = Some((read, npos));
                        self.last_nl_pos = Some(n + end);
                        self.next()
                    }
                }
            },
            // depleted
            (None, None) => None,
            (Some(_), None) => unreachable!("BUG: Invalid state: we never discard only our file, always both."),
        }
    }
}

View on GitHub (pinned to e73179060b)