GitoxideLabs/gitoxide · error
non zero
Error message
non zero
What it means
`gix_pack::cache::object::MemoryCappedHashmap::new` requires a non-zero memory cap because the underlying clru cache is built from a `NonZeroUsize`. A cap of 0 bytes would create a cache that can never hold an item, so the constructor panics with 'non zero'.
Solutions
- Provide a non-zero byte value for the memory cap
- Clamp the value before construction: `cap.max(1)` or substitute a default when 0
- Skip cache construction entirely if a 0 cap means 'disabled' in your app
Example fix
// before
let cache = object::MemoryCappedHashmap::new(bytes);
// after
let cache = if bytes == 0 { None } else { Some(object::MemoryCappedHashmap::new(bytes)) }; Defensive patterns
Strategy: validation
Validate before calling
let cap = if bytes == 0 { DEFAULT_OBJECT_CACHE_BYTES } else { bytes }; Prevention
- Validate object-cache size config before constructing caches
- Map a 0 setting to 'no cache' in your own code rather than passing it through
- Add config round-trip tests covering zero and negative-ish inputs
When it happens
Trigger: Calling `gix_pack::cache::object::MemoryCappedHashmap::new(0)` — typically when a configured object-cache size in bytes is 0.
Common situations: Users setting `object-cache-memory-bytes = 0` in config expecting to disable caching; config defaults resolved to 0.
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/95b00d16d73233ac.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/cache/object.rs:45
/// 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, gix_hashtable::hash::Builder, CustomScale>,
free_list: Vec<Vec<u8>>,
debug: gix_features::cache::Debug,
}
impl MemoryCappedHashmap {
/// The amount of bytes we can hold in total, or the value we saw in `new(…)`.
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
/// 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_hasher(gix_hashtable::hash::Builder)
.with_scale(CustomScale),
),
free_list: Vec::new(),
debug: gix_features::cache::Debug::new(format!("MemoryCappedObjectHashmap({memory_cap_in_bytes}B)")),
}
}
}
impl cache::Object for MemoryCappedHashmap {
/// Put the object going by `id` of `kind` with `data` into the cache.
fn put(&mut self, id: gix_hash::ObjectId, kind: gix_object::Kind, data: &[u8]) {
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(id, Entry { data, kind });
match res {View on GitHub (pinned to e73179060b)