GitoxideLabs/gitoxide · error
non zero
Error message
non zero
What it means
`MemoryCappedHashmap::new` wraps its byte limit in a `NonZeroUsize` for clru's cache; a zero memory cap is a programming error because a cache that can hold nothing is meaningless. It panics with 'non zero' when `memory_cap_in_bytes == 0`.
Solutions
- Pass a non-zero memory cap (e.g. 64 * 1024 * 1024 for 64 MiB)
- Validate/clamp the config value before constructing: `if cap == 0 { cap = DEFAULT_CAP }`
- Use a cache-free code path if caching is unwanted rather than a 0 cap
Example fix
// before let cache = MemoryCappedHashmap::new(config.memory_cap); // panics if 0 // after let cap = config.memory_cap.max(1); let cache = MemoryCappedHashmap::new(cap);
Defensive patterns
Strategy: validation
Validate before calling
assert!(memory_cap_in_bytes > 0, "memory cap must be non-zero"); // or: let cap = memory_cap_in_bytes.max(1);
Prevention
- Clamp config-supplied cache sizes with .max(1) or a default constant
- Document that 0 is not a valid cap; use explicit 'disabled' handling instead
- Unit-test config parsing for zero values
When it happens
Trigger: Constructing `gix_pack::cache::lru::MemoryCappedHashmap::new(0)`, usually from a configuration value of 0 for the object cache memory cap.
Common situations: Configuration mistakes: users setting cache memory to 0 intending 'unlimited' (it actually means 'no capacity at all'); config parsed as 0 by default.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- non zero
- ' ' is not a valid configuration key
- Cannot use iter_v1() on index of type
- Cannot use iter_v2() on index of type
- BUG: tries to obtain object id from symbolic target
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/4d4fb8f9e8b50ad7.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/cache/lru.rs:40
fn weight(&self, _key: &Key, value: &Entry) -> usize {
value.data.len()
}
}
/// An LRU cache with hash map backing and an eviction rule based on the memory usage for object data in bytes.
pub struct MemoryCappedHashmap {
inner: clru::CLruCache<Key, Entry, std::collections::hash_map::RandomState, CustomScale>,
free_list: Vec<Vec<u8>>,
debug: gix_features::cache::Debug,
}
impl MemoryCappedHashmap {
/// Return a new instance which evicts least recently used items if it uses more than `memory_cap_in_bytes`
/// object data.
pub fn new(memory_cap_in_bytes: usize) -> MemoryCappedHashmap {
MemoryCappedHashmap {
inner: clru::CLruCache::with_config(
clru::CLruCacheConfig::new(NonZeroUsize::new(memory_cap_in_bytes).expect("non zero"))
.with_scale(CustomScale),
),
free_list: Vec::new(),
debug: gix_features::cache::Debug::new(format!("MemoryCappedHashmap({memory_cap_in_bytes}B)")),
}
}
}
impl DecodeEntry for MemoryCappedHashmap {
fn put(&mut self, pack_id: u32, offset: u64, data: &[u8], kind: gix_object::Kind, compressed_size: usize) {
self.debug.put();
let Some(data) = set_vec_to_slice(self.free_list.pop().unwrap_or_default(), data) else {
return;
};
let res = self.inner.put_with_weight(
(pack_id, offset),
Entry {
data,View on GitHub (pinned to e73179060b)