GitoxideLabs/gitoxide · error

Cannot use iter_v2() on index of type

Error message

Cannot use iter_v2() on index of type {:?}

What it means

`gix_pack::index::File::iter_v2()` only works on pack index version V2. On any other version (i.e. V1) the match arm `_ => panic!` fires. It mirrors the iter_v1 panic: version-specific accessors must only be called on matching index versions.

Solutions

  1. Call `index_file.iter()` which handles both versions automatically
  2. Guard with `if index_file.version == index::Version::V2` before calling `iter_v2()`
  3. Use `iter_v1()` for V1 indexes
  4. Rewrite the pack index with `git index-pack` to upgrade to v2

Example fix

// before
let entries = index_file.iter_v2(); // panics on v1 indexes
// after
let entries = match index_file.version {
    gix_pack::index::Version::V2 => index_file.iter_v2().collect(),
    _ => index_file.iter_v1().collect(),
};
Defensive patterns

Strategy: validation

Validate before calling

if index_file.version == gix_pack::index::Version::V2 {
    let entries: Vec<_> = index_file.iter_v2().collect();
} else {
    let entries: Vec<_> = index_file.iter().collect();
}

Type guard

fn supports_v2(index: &gix_pack::index::File) -> bool {
    index.version == gix_pack::index::Version::V2
}

Prevention

When it happens

Trigger: Calling `index_file.iter_v2()` on a `Version::V1` index; assuming all .idx files are v2 (git's modern default) and calling the v2 accessor directly.

Common situations: Reading old repositories cloned before git 1.6 that still carry v1 indexes; fixtures or test repos with v1 packs; custom tooling that skips the `iter()` dispatcher.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at gix-pack/src/index/access.rs:74

        let crcs = self.data[self.offset_crc32_v2()..]
            .as_chunks::<N32_SIZE>()
            .0
            .iter()
            .take(self.num_objects as usize);
        let offsets = self.data[self.offset_pack_offset_v2()..]
            .as_chunks::<N32_SIZE>()
            .0
            .iter()
            .take(self.num_objects as usize);
        assert_eq!(oids.len(), crcs.len());
        assert_eq!(crcs.len(), offsets.len());
        match self.version {
            index::Version::V2 => izip!(oids, crcs, offsets).map(move |(oid, crc32, ofs32)| Entry {
                oid: gix_hash::ObjectId::from_bytes_or_panic(oid),
                pack_offset: self.pack_offset_from_offset_v2(ofs32, pack64_offset),
                crc32: Some(crate::read_u32(crc32)),
            }),
            _ => panic!("Cannot use iter_v2() on index of type {:?}", self.version),
        }
    }

    /// Returns the object hash at the given index in our list of (sorted) sha1 hashes.
    /// The index ranges from 0 to `self.num_objects()`
    ///
    /// # Panics
    ///
    /// If `index` is out of bounds.
    pub fn oid_at_index(&self, index: EntryIndex) -> &gix_hash::oid {
        let index = index as usize;
        let start = match self.version {
            index::Version::V2 => V2_HEADER_SIZE + index * self.hash_len,
            index::Version::V1 => V1_HEADER_SIZE + index * (N32_SIZE + self.hash_len) + N32_SIZE,
        };
        gix_hash::oid::from_bytes_unchecked(&self.data[start..][..self.hash_len])
    }

View on GitHub (pinned to e73179060b)