{"record":{"id":"95b00d16d73233ac","repo":"GitoxideLabs/gitoxide","slug":"non-zero-95b00d","errorCode":null,"errorMessage":"non zero","messagePattern":"non zero","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-pack/src/cache/object.rs","lineNumber":45,"sourceCode":"\n    /// An LRU cache with hash map backing and an eviction rule based on the memory usage for object data in bytes.\n    pub struct MemoryCappedHashmap {\n        inner: clru::CLruCache<Key, Entry, gix_hashtable::hash::Builder, CustomScale>,\n        free_list: Vec<Vec<u8>>,\n        debug: gix_features::cache::Debug,\n    }\n\n    impl MemoryCappedHashmap {\n        /// The amount of bytes we can hold in total, or the value we saw in `new(…)`.\n        pub fn capacity(&self) -> usize {\n            self.inner.capacity()\n        }\n        /// Return a new instance which evicts least recently used items if it uses more than `memory_cap_in_bytes`\n        /// object data.\n        pub fn new(memory_cap_in_bytes: usize) -> MemoryCappedHashmap {\n            MemoryCappedHashmap {\n                inner: clru::CLruCache::with_config(\n                    clru::CLruCacheConfig::new(NonZeroUsize::new(memory_cap_in_bytes).expect(\"non zero\"))\n                        .with_hasher(gix_hashtable::hash::Builder)\n                        .with_scale(CustomScale),\n                ),\n                free_list: Vec::new(),\n                debug: gix_features::cache::Debug::new(format!(\"MemoryCappedObjectHashmap({memory_cap_in_bytes}B)\")),\n            }\n        }\n    }\n\n    impl cache::Object for MemoryCappedHashmap {\n        /// Put the object going by `id` of `kind` with `data` into the cache.\n        fn put(&mut self, id: gix_hash::ObjectId, kind: gix_object::Kind, data: &[u8]) {\n            self.debug.put();\n            let Some(data) = set_vec_to_slice(self.free_list.pop().unwrap_or_default(), data) else {\n                return;\n            };\n            let res = self.inner.put_with_weight(id, Entry { data, kind });\n            match res {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-pack/src/cache/object.rs#L27-L63","documentation":"`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'.","triggerScenarios":"Calling `gix_pack::cache::object::MemoryCappedHashmap::new(0)` — typically when a configured object-cache size in bytes is 0.","commonSituations":"Users setting `object-cache-memory-bytes = 0` in config expecting to disable caching; config defaults resolved to 0.","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"],"exampleFix":"// before\nlet cache = object::MemoryCappedHashmap::new(bytes);\n// after\nlet cache = if bytes == 0 { None } else { Some(object::MemoryCappedHashmap::new(bytes)) };","handlingStrategy":"validation","validationCode":"let cap = if bytes == 0 { DEFAULT_OBJECT_CACHE_BYTES } else { bytes };","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","panic","cache","zero-value","configuration"],"backgroundTag":"invalid-argument-value","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}