GitoxideLabs/gitoxide · error
BUG: a slot can never be deleted if we have it recorded in…
Error message
BUG: a slot can never be deleted if we have it recorded in the index WHILE changing said index. There shouldn't be a race
What it means
`assure_slot_matches_index` in `gix-odb`'s dynamic object store looks up a pack slot recorded in an in-memory index; the `None` arm panics because a slot being consulted cannot be removed concurrently by design (single-writer access to the index). Hitting it means the slot bookkeeping was mutated unexpectedly.
Solutions
- Report upstream with repository layout (pack files, multi-pack-index) and the operation that panicked.
- Update `gix-odb`/`gix` to the latest version.
- If maintaining, replace `unreachable!` with an error indicating a lost slot for diagnosability.
Example fix
// before
None => unreachable!("BUG: a slot can never be deleted ..."),
// after
None => return Err(message("BUG: multi-index slot missing while consulting index; store state corrupted")) Defensive patterns
Strategy: try-catch
Try / catch
// Not user-triggerable; wrap object loads in catch_unwind for resilience. let obj = std::panic::catch_unwind(|| repo.find_object(id));
Prevention
- Avoid custom slot/index manipulation in forked code
- Keep gix-odb current
- Verify repository integrity with fsck-style checks
When it happens
Trigger: Only if slot replacement/removal logic in the multi-pack index races or double-frees an entry — e.g. a refactor bug around `MultiIndexSlotMap` removal while a `load_index` operation holds a lookup.
Common situations: Not expected in normal use of a repository with many pack files and multi-pack indices; would appear as a panic while loading objects.
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
- only value and unspecified are possible here
- parent-match assures this
- upper match already assured we only deal with blobs
- fixed size array with three items
- internal nodes have no object ID key
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/0cbe10c8c1f7aaa6.
Report an issue: GitHub.
Appendix: source
Thrown at gix-odb/src/store_impls/dynamic/load_index.rs:655
.expect("BUG: cannot change from something to nothing, would be race");
files_mut.put_back();
debug_assert_eq!(
files_mut.mtime(),
mtime,
"BUG: we can only put back files that didn't obviously change"
);
// Safety: can't race as we hold the lock, must be set before replacing the data.
// NOTE that we don't change the generation as it's still the very same index we talk about, it doesn't change
// identity.
slot.generation.store(current_generation, Ordering::SeqCst);
slot.files.store(files);
} else {
// it's already in the correct state, either loaded or unloaded.
}
bundle.index_is_loaded()
}
None => {
unreachable!(
"BUG: a slot can never be deleted if we have it recorded in the index WHILE changing said index. There shouldn't be a race"
)
}
}
}
/// Stability means that indices returned by this API will remain valid.
/// Without that constraint, we may unload unused packs and indices, and may rebuild the slotmap index.
///
/// Note that this must be called with a lock to the relevant state held to assure these values don't change while
/// we are working on said index.
fn maintain_stable_indices(&self, _guard: &parking_lot::MutexGuard<'_, ()>) -> bool {
self.num_handles_stable.load(Ordering::SeqCst) > 0
}
pub(crate) fn collect_snapshot(&self) -> Snapshot {
// We don't observe changes-on-disk in our 'wait-for-load' loop.
// That loop is meant to help assure the marker (which includes the amount of loaded indices) matchesView on GitHub (pinned to e73179060b)