quickwit-oss/tantivy · error
Failed to acquire read lock on SegmentManager.
Error message
Failed to acquire read lock on SegmentManager.
What it means
SegmentManager::read (src/indexer/segment_manager.rs:107) unwraps a RwLock read guard on the segment registers and panics with this message if the lock is poisoned. The comment above it states the lock is acquired and released only inside SegmentManager and its operations are designed not to panic, so poisoning indicates an internal invariant violation — usually following another panic during segment operations (commit, merge, garbage collection).
Source
Thrown at src/indexer/segment_manager.rs:107
.uncommitted
.get_mergeable_segments(in_merge_segment_ids),
)
}
/// Returns all of the segment entries (committed or uncommitted)
pub fn segment_entries(&self) -> Vec<SegmentEntry> {
let registers_lock = self.read();
let mut segment_entries = registers_lock.uncommitted.segment_entries();
segment_entries.extend(registers_lock.committed.segment_entries());
segment_entries
}
// Lock poisoning should never happen :
// The lock is acquired and released within this class,
// and the operations cannot panic.
fn read(&self) -> RwLockReadGuard<'_, SegmentRegisters> {
self.registers
.read()
.expect("Failed to acquire read lock on SegmentManager.")
}
fn write(&self) -> RwLockWriteGuard<'_, SegmentRegisters> {
self.registers
.write()
.expect("Failed to acquire write lock on SegmentManager.")
}
/// Deletes all empty segments
fn remove_empty_segments(&self) {
let mut registers_lock = self.write();
registers_lock
.committed
.segment_entries()
.iter()
.filter(|segment| segment.meta().num_docs() == 0)
.for_each(|segment| {
registers_lockView on GitHub (pinned to b5d8deb80c)
Solutions
- Fix the root-cause panic that happened while the write lock was held; the first panic in your logs is the real error.
- After a panic, discard the Index and reopen it from disk rather than continuing with the poisoned SegmentManager.
- Wrap indexing/commit code so a panic tears down the whole writer+reader set, not just one thread.
- Check custom DocMapping/segment-merge callbacks for panics and convert those error paths to Result instead.
- Report to tantivy if reproducible without an application-side panic.
Example fix
// before: keep using reader after worker panic
std::panic::catch_unwind(|| writer.commit()).ok();
let segs = reader.searcher().segment_readers(); // may hit poisoned lock
// after: reopen on panic
if std::panic::catch_unwind(|| writer.commit()).is_err() {
(writer, reader) = Index::open_in_dir(&dir)?; // fresh SegmentManager
} Defensive patterns
Strategy: try-catch
Try / catch
match std::panic::catch_unwind(AssertUnwindSafe(|| writer.commit())) {
Ok(r) => r?,
Err(_) => { (writer, reader) = reopen_index()?; }
} Prevention
- Fix the first panic in your logs — it is the root cause
- Tear down writer+reader together after a panic
- Avoid panicking custom DocMapper/merge callbacks; return Result
- Upgrade tantivy for known internal bugs; keep segments uncorrupted
When it happens
Trigger: Any read-path call — fmt/debug printing, get_mergeable_segments, segment_entries, start_merge, committed_segment_metas — after a thread panicked while holding the SegmentManager write lock (e.g. during commit, add_segment or end_merge).
Common situations: An indexing/commit thread panics (e.g. on a schema mismatch or corrupted segment) while other reader threads continue using the same IndexReader/writer; long-lived services that swallow panics in worker threads; bugs in custom DocMappers or custom scorers that panic during commit.
Related errors
- This lock should never be poisoned
- Failed to acquire write lock on SegmentManager.
- Failed to acquire write lock on delete queue writer
- Empty DocOpstamp is forbidden
- Invalid type code in JSON term
AI-assisted analysis of quickwit-oss/tantivy@b5d8deb80c (2026-09-05).
Data as JSON: /api/errors/7c52edd660c06e4a.
Report an issue: GitHub.