quickwit-oss/quickwit · error

stdin cannot be checkpointed

Error message

stdin cannot be checkpointed

What it means

ByteRangeCacheDirectory (the shared factory) keeps a Mutex-protected map of per-path FileByteRangeCaches. get_file_cache locks that map and `.expect`s the result. The panic occurs only when the map's mutex is poisoned — a thread previously panicked while holding this lock. The tests calling this helper would surface such a poisoning as a hard failure.

Source

Thrown at quickwit/quickwit-metastore/src/metastore/mod.rs:1516

            end: Bound::Unbounded,
        }
    }
}

/// Maps the given source params to whether checkpoints should be stored in the index metadata
/// (false) or the shard table (true)
fn use_shard_api(params: &SourceParams) -> bool {
    match params {
        SourceParams::File(FileSourceParams::Filepath(_)) => false,
        SourceParams::File(FileSourceParams::Notifications(_)) => true,
        SourceParams::Ingest => true,
        SourceParams::IngestApi => false,
        SourceParams::IngestCli => false,
        SourceParams::Kafka(_) => false,
        SourceParams::Kinesis(_) => false,
        SourceParams::PubSub(_) => false,
        SourceParams::Pulsar(_) => false,
        SourceParams::Stdin => panic!("stdin cannot be checkpointed"),
        SourceParams::Vec(_) => false,
        SourceParams::Void(_) => false,
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_filter_contains() {
        let filter = FilterRange {
            start: Bound::Unbounded,
            end: Bound::Excluded(50),
        };
        assert!(!filter.contains(&50));
        assert!(filter.contains(&0));
        assert!(filter.contains(&49));

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Find the initial panic that poisoned the map (first occurrence in the logs) and fix that bug.
  2. Restart the process; poisoned mutexes never recover within a process.
  3. Report with a backtrace of the original panic — panicking while constructing/inserting a file cache is a bug.
  4. As a defensive code change, use `unwrap_or_else(|poisoned| poisoned.into_inner())` since map entries are individually consistent.

Example fix

// before
let mut file_caches = self
    .inner_arc
    .file_caches
    .lock()
    .expect("byte range cache mutex is poisoned");
// after
let mut file_caches = self
    .inner_arc
    .file_caches
    .lock()
    .unwrap_or_else(|poisoned| poisoned.into_inner());
Defensive patterns

Strategy: retry

Try / catch

// in tests: assert no panic occurred before asserting map behavior
let result = std::panic::catch_unwind(|| shared_cache.get_file_cache(path));
assert!(result.is_ok(), "file_caches mutex was poisoned by an earlier panic");

Prevention

When it happens

Trigger: A thread panicking while holding the `file_caches` map lock (e.g. during FileByteRangeCache construction in an earlier get_file_cache call or a panic in map insertion), then any subsequent get_file_cache call — in production code or in tests like test_byte_range_cache_is_shared_for_same_path — panics.

Common situations: A bug during cache creation for one path poisons the map; all later storages built on the same shared cache instance then fail; typically observed as a cascade of identical panics across threads.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/6ccb2e52eb43e28c. Report an issue: GitHub.