quickwit-oss/quickwit · error

attempted to merge zero splits

Error message

attempted to merge zero splits

What it means

Merge execution computes split attributes (doc mapping uid, delete opstamp, etc.) from the list of splits to merge. An empty split list is an invariant violation — merges are only supposed to be scheduled with at least two splits — so `merge_split_attrs` fails on `splits.first()` with this error. It indicates a bug in merge scheduling rather than user input.

Source

Thrown at quickwit/quickwit-indexing/src/actors/merge_executor.rs:293

    merge_split_id: SplitId,
    splits: &[SplitMetadata],
) -> anyhow::Result<SplitAttrs> {
    let partition_id = combine_partition_ids_aux(splits.iter().map(|split| split.partition_id));
    let time_range: Option<RangeInclusive<DateTime>> = merge_time_range(splits);
    let uncompressed_docs_size_in_bytes = sum_doc_sizes_in_bytes(splits);
    let num_docs = sum_num_docs(splits);
    let replaced_split_ids: Vec<SplitId> = splits
        .iter()
        .map(|split| split.split_id().clone())
        .collect();
    let delete_opstamp = splits
        .iter()
        .map(|split| split.delete_opstamp)
        .min()
        .unwrap_or(0);
    let doc_mapping_uid = splits
        .first()
        .ok_or_else(|| anyhow::anyhow!("attempted to merge zero splits"))?
        .doc_mapping_uid;
    if splits
        .iter()
        .any(|split| split.doc_mapping_uid != doc_mapping_uid)
    {
        anyhow::bail!("attempted to merge splits with different doc mapping uid");
    }
    Ok(SplitAttrs {
        node_id: pipeline_id.node_id.clone(),
        index_uid: pipeline_id.index_uid.clone(),
        source_id: pipeline_id.source_id.clone(),
        doc_mapping_uid,
        split_id: merge_split_id,
        partition_id,
        replaced_split_ids,
        time_range,
        num_docs,
        uncompressed_docs_size_in_bytes,

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Investigate the merge planner/scheduler that emitted an empty merge task; this is an internal invariant violation.
  2. Check the indexing pipeline logs for the task that produced the empty split list.
  3. Filter out empty merge tasks before dispatching to the merge actor.
  4. If reproducible, report it as a Quickwit bug with the offending merge task.
Defensive patterns

Strategy: try-catch

Try / catch

match merge_executor.merge(task) {
    Err(e) if e.to_string().contains("attempted to merge zero splits") => {
        // log and drop the empty merge task; investigate planner
    }
    r => r?,
}

Prevention

When it happens

Trigger: `process_merge` or `fake_merge` in the merge actor invokes `merge_split_attrs` with an empty `Vec<Split>` — i.e. the merge planner produced an empty merge task or the splits list was drained before execution.

Common situations: Race between merge planning and split deletion, corrupted merge task payloads, or custom/test code calling `fake_merge` with no splits.

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/7b9190fe35794f54. Report an issue: GitHub.