GitoxideLabs/gitoxide · error

BUG: pack now is smaller than all previously seen entries

Error message

BUG: pack now is smaller than all previously seen entries

What it means

The delta-tree cache used during pack traversal tracks pack entry offsets monotonically. `set_pack_entries_end_and_resolve_ref_offsets` asserts the new pack end offset is not smaller than all previously seen entries via `assert_is_incrementing_and_update_next_offset`. The panic signals a corrupted pack file where an entry's offset runs backwards, breaking the tree's invariants.

Solutions

  1. Re-download or re-clone the repository to obtain a fresh pack
  2. Run `git fsck --full` / `gix --verbose pack verify` to confirm corruption
  3. Delete the local objects directory content and re-fetch (`git fetch --refetch` or fresh clone)

Example fix

// before (caller assumes pack is intact)
bundle.traverse(...)?;
// after
// validate pack integrity first; a corrupted pack must be re-fetched, not patched
if let Err(e) = bundle.traverse(...) { eprintln!("pack corrupt: {e}; re-fetch required"); }
Defensive patterns

Strategy: validation

Validate before calling

// check pack integrity before traversal
run gitoxide/gix pack verify (or `git fsck --full`) before indexing untrusted packs

Try / catch

let outcome = std::panic::catch_unwind(|| bundle.traverse(...));
match outcome { Err(_) => eprintln!("pack structurally corrupt - re-fetch required"), Ok(r) => r? }

Prevention

When it happens

Trigger: Running `traverse()` (e.g. pack verification or index writing via `gix_pack::data::File::verify_checksum`/`Bundle::traverse`) over a pack file whose entries are not sorted by ascending pack offset, typically due to pack corruption.

Common situations: Verifying or indexing corrupted/downloaded packs; interrupted pack transfers; disk corruption; manually concatenated pack files.

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

Appendix: source

Thrown at gix-pack/src/cache/delta/tree.rs:128

                //  - We are draining from future_child_offsets and adding to children, keeping things the same.
                //  - We can rely on the `future_child_offsets` invariant to be sure that `children` is
                //    not getting any indices that are already in use in `children` elsewhere
                //  - The indices are in bounds for child_items since they were in bounds for future_child_offsets,
                //    we can carry over the invariant.
                if let Ok(i) = self.child_items.binary_search_by_key(&parent_offset, |i| i.offset) {
                    self.child_items[i].children.push(child_index as u32);
                } else if let Ok(i) = self.root_items.binary_search_by_key(&parent_offset, |i| i.offset) {
                    self.root_items[i].children.push(child_index as u32);
                } else {
                    return Err(traverse::Error::OutOfPackRefDelta {
                        base_pack_offset: parent_offset,
                    });
                }
            }
        }

        self.assert_is_incrementing_and_update_next_offset(pack_entries_end)
            .expect("BUG: pack now is smaller than all previously seen entries");
        Ok(())
    }

    /// Add a new root node, one that only has children but is not a child itself, at the given pack `offset` and associate
    /// custom `data` with it.
    pub(crate) fn add_root(&mut self, offset: crate::data::Offset, data: T) -> Result<(), Error> {
        self.assert_is_incrementing_and_update_next_offset(offset)?;
        self.last_seen = NodeKind::Root.into();
        self.root_items.push(Item {
            offset,
            next_offset: 0,
            data,
            // SAFETY INVARIANT upheld: there are no children
            children: Default::default(),
        });
        Ok(())
    }

View on GitHub (pinned to e73179060b)