quickwit-oss/tantivy · error
Field reader cache lock poisoned. This should never happen.
Error message
Field reader cache lock poisoned. This should never happen.
What it means
This is the write side of the same inverted-index reader cache in SegmentReader: after a cache miss, the reader is inserted under a write lock whose poisoning triggers this panic. Like the read side, poisoning implies a thread panicked while holding the cache lock.
Source
Thrown at src/index/segment_reader.rs:284
"Failed to open field {:?}'s positions in the composite file. Has the schema been \
modified?",
field_entry.name()
);
DataCorruption::comment_only(error_msg)
})?;
let inv_idx_reader = Arc::new(InvertedIndexReader::new(
TermDictionary::open(termdict_file)?,
postings_file,
positions_file,
record_option,
)?);
// by releasing the lock in between, we may end up opening the inverting index
// twice, but this is fine.
self.inv_idx_reader_cache
.write()
.expect("Field reader cache lock poisoned. This should never happen.")
.insert(field, Arc::clone(&inv_idx_reader));
Ok(inv_idx_reader)
}
/// Returns the list of fields that have been indexed in the segment.
/// The field list includes the field defined in the schema as well as the fields
/// that have been indexed as a part of a JSON field.
/// The returned field name is the full field name, including the name of the JSON field.
///
/// The returned field names can be used in queries.
///
/// Notice: If your data contains JSON fields this is **very expensive**, as it requires
/// browsing through the inverted index term dictionary and the columnar field dictionary.
///
/// Disclaimer: Some fields may not be listed here. For instance, if the schema contains a json
/// field that is not indexed nor a fast field but is stored, it is possible for the field
/// to not be listed.View on GitHub (pinned to b5d8deb80c)
Solutions
- Fix the root panic that poisoned the lock (check earlier stack traces for InvertedIndexReader::open failures).
- Repair or re-index the affected segment.
- Recreate the SegmentReader/Searcher after the failure.
- Reduce concurrency-induced panics by validating index integrity before searching.
Example fix
// before
let inv = reader.inverted_index(field)?; // panics: cache lock poisoned
// after: guard against root cause first
let inv = if segment_has_valid_index_files(seg) { reader.inverted_index(field)? } else { return Err(corrupt_segment_err) }; Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
segment_reader.inverted_index(field)
}));
if res.is_err() { searcher = rebuild_searcher(&reader)?; } Prevention
- Fix root causes of panics during InvertedIndexReader::open (corrupt files)
- Re-index damaged segments promptly
- Avoid sharing one SegmentReader across threads after failures
- Run search workers with catch_unwind isolation
When it happens
Trigger: First access to a field's inverted index on a segment triggers a write-lock insert while another thread has panicked holding that lock; reached via inverted_index(), scorer, phrase_scorer, fields_metadata, or get_match_term_infos.
Common situations: Concurrent searches where one thread panics inside InvertedIndexReader::open (corrupt store/idx files), then other threads panic here on cache insert.
Related errors
- Lock poisoned. This should never happen
- Mmap cache lock is poisoned.
- Failed to acquire write lock in delete queue
- Failed to acquire write lock on delete queue writer
- This lock should never be poisoned
AI-assisted analysis of quickwit-oss/tantivy@b5d8deb80c (2026-09-05).
Data as JSON: /api/errors/1cef2c6e16cb3e52.
Report an issue: GitHub.