quickwit-oss/tantivy · critical
No multivalued index is allowed when stacking column index
Error message
No multivalued index is allowed when stacking column index
What it means
When stacking (merging) columnar column indexes, the code can only handle Optional (single-valued) and Empty indexes. If a Multivalued column index is encountered it cannot be expressed as a flat row iterator, so the library panics. This is an internal invariant violation: a multivalued column reached a merge path that only supports single-valued columns.
Source
Thrown at columnar/src/column_index/merge/stacked.rs:185
}
impl<'a> Iterable<RowId> for StackedOptionalIndex<'a> {
fn boxed_iter(&self) -> Box<dyn Iterator<Item = RowId> + 'a> {
Box::new(
self.columns
.iter()
.enumerate()
.flat_map(|(columnar_id, column_index_opt)| {
let columnar_row_range = self.stack_merge_order.columnar_range(columnar_id);
let rows_it: Box<dyn Iterator<Item = RowId>> = match column_index_opt {
ColumnIndex::Full => Box::new(columnar_row_range),
ColumnIndex::Optional(optional_index) => Box::new(
optional_index
.iter_non_null_docs()
.map(move |row_id: RowId| columnar_row_range.start + row_id),
),
ColumnIndex::Multivalued(_) => {
panic!("No multivalued index is allowed when stacking column index");
}
ColumnIndex::Empty { .. } => Box::new(std::iter::empty()),
};
rows_it
}),
)
}
}
View on GitHub (pinned to b5d8deb80c)
Solutions
- Do not stack/merge multivalued columns with this API; check column cardinality first and skip or handle multivalued columns separately.
- Use the multivalued-aware merge path (e.g. merging full columns with Column::merge, which handles multivalued indexes) instead of the stacked index merge.
- If this is unexpected, verify the column's index type with a debug assert and report a bug to tantivy-columnar maintainers with the segment data.
Example fix
// before
for column in columns {
stacked.push(column.stack(other)); // panics on multivalued
}
// after
for column in columns {
if column.get_cardinality() != Cardinality::Multivalued {
stacked.push(column.stack(other));
} else {
// handle multivalued columns via the full-column merge API
merged_multivalued.push(Column::merge(column.clone(), other.clone()));
}
} Defensive patterns
Strategy: validation
Validate before calling
if column.get_cardinality() == Cardinality::Multivalued {
return Err("cannot stack multivalued column".into());
}
stacked.push(column.stack(other)); Type guard
fn is_stackable(card: Cardinality) -> bool {
matches!(card, Cardinality::Optional | Cardinality::Full)
} Prevention
- Check column cardinality before any stack/merge call
- Route multivalued columns to the multivalued-aware merge API
- Log/skip unsupported column types when iterating table columns
When it happens
Trigger: Calling columnar stack/merge APIs (e.g. stacking columns via Column::merge / stacked column building) on a column whose ColumnIndex is ColumnIndex::Multivalued; i.e. merging a multivalued (array) column through the stacked column-index merge path in columnar/src/column_index/merge/stacked.rs.
Common situations: Merging or stacking segments/tables that contain array (multivalued) fields; passing a column built from repeated values into an API documented for single-valued columns; custom tooling that iterates all columns of a table and stacks them without filtering column type (multivalued => Cardinality::Multivalued).
Related errors
- All columns re required to be numerical
- Internal Error: Called get_val of empty column.
- interval not precomputed for date histogram source
- InvalidInput
- Invalid op metadata byte
AI-assisted analysis of quickwit-oss/tantivy@b5d8deb80c (2026-09-05).
Data as JSON: /api/errors/fa6a4874b3c20fbb.
Report an issue: GitHub.