{"record":{"id":"bf2d79c324e65107","repo":"quickwit-oss/tantivy","slug":"mmap-cache-lock-is-poisoned-bf2d79","errorCode":null,"errorMessage":"Mmap cache lock is poisoned.","messagePattern":"Mmap cache lock is poisoned\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/directory/mmap_directory/mod.rs","lineNumber":301,"sourceCode":"    fn resolve_path(&self, relative_path: &Path) -> PathBuf {\n        self.inner.root_path.join(relative_path)\n    }\n\n    /// Returns some statistical information\n    /// about the Mmap cache.\n    ///\n    /// The `MmapDirectory` embeds a `MmapDirectory`\n    /// to avoid multiplying the `mmap` system calls.\n    pub fn get_cache_info(&self) -> CacheInfo {\n        self.inner\n            .mmap_cache\n            .write()\n            .expect(\"mmap cache lock is poisoned\")\n            .remove_weak_ref();\n        self.inner\n            .mmap_cache\n            .read()\n            .expect(\"Mmap cache lock is poisoned.\")\n            .get_info()\n    }\n}\n\n/// We rely on fs2 for file locking. On Windows & MacOS this\n/// uses BSD locks (`flock`). The lock is actually released when\n/// the `File` object is dropped and its associated file descriptor\n/// is closed.\nstruct ReleaseLockFile {\n    _file: File,\n    path: PathBuf,\n}\n\nimpl Drop for ReleaseLockFile {\n    fn drop(&mut self) {\n        debug!(\"Releasing lock {:?}\", self.path);\n    }\n}","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/directory/mmap_directory/mod.rs#L283-L319","documentation":"This panic occurs when the RwLock guarding the segment mmap cache is poisoned, i.e. another thread panicked while holding the read or write lock on that cache. Tantivy uses expect() here because lock poisoning on an internal cache means a prior thread crashed mid-operation, leaving the cache in an indeterminate state.","triggerScenarios":"A panic happens in another thread while it holds the mmap cache lock (e.g. during cache eviction or weak-ref removal), then any thread calls get_cache_info().","commonSituations":"A background indexing or search thread panics (e.g. corrupt segment, OOM during mmap) while holding the cache lock; the panic message seen is the propagated poisoning, not the root cause.","solutions":["Find and fix the original panic that poisoned the lock (scan earlier logs for the root panic/backtrace).","Reinitialize the index reader/searcher after the panic instead of reusing the same Index across threads.","Ensure custom Directory/wrap implementations do not panic while accessing mmap cache internals.","If caused by memory pressure, reduce concurrent mmap usage or increase address space / mmap limits."],"exampleFix":"// before: reusing a shared Index across threads after a panic\nlet info = index.get_cache_info(); // panics: poisoned\n// after: recreate the index handle after catching the root failure\nlet index = Index::open_in_dir(&dir)?;\nlet info = index.get_cache_info();","handlingStrategy":"try-catch","validationCode":"// Rust: check index dir is readable/mmap-able before use\nstd::fs::read(dir.join(\"meta.json\")).map_err(|e| format!(\"index unreadable: {e}\"))?;","typeGuard":"fn lock_ok<T>(guard: std::sync::LockResult<T>) -> Option<T> { guard.ok() }","tryCatchPattern":"let info = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| index.get_cache_info()));\nmatch info {\n    Ok(v) => use(v),\n    Err(_) => { let index = reopen_index(&dir)?; }\n}","preventionTips":["Fix root panics in worker threads before they poison shared locks","Recreate Index/Searcher handles after any caught panic","Avoid panicking inside custom Directory or cache code","Monitor logs for earlier panics — this error is always secondary"],"tags":["rust","panic","mutex-poisoning","concurrency"],"backgroundTag":"mutex-poisoned","analyzedSha":"b5d8deb80c26924e6b007a5b1a7630f35ca64de4","analyzedAt":"2026-09-05T13:20:51.521Z","contentChangedAt":"2026-09-05T13:20:51.521Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}