{"record":{"id":"dd278eebe82c08c8","repo":"quickwit-oss/tantivy","slug":"all-columns-re-required-to-be-numerical","errorCode":null,"errorMessage":"All columns re required to be numerical","messagePattern":"All columns re required to be numerical","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"columnar/src/columnar/merge/mod.rs","lineNumber":343,"sourceCode":"        self.required_column_type = Some(required_type);\n        Ok(())\n    }\n}\n\n/// Returns the type of the merged numerical column.\n///\n/// This function picks the first numerical type out of i64, u64, f64 (order matters\n/// here), that is compatible with all the `columns`.\n///\n/// # Panics\n/// Panics if one of the column is not numerical.\nfn merged_numerical_columns_type<'a>(\n    columns: impl Iterator<Item = &'a DynamicColumn>,\n) -> NumericalType {\n    let mut compatible_numerical_types = CompatibleNumericalTypes::default();\n    for column in columns {\n        let (min_value, max_value) =\n            min_max_if_numerical(column).expect(\"All columns re required to be numerical\");\n        compatible_numerical_types.accept_value(min_value);\n        compatible_numerical_types.accept_value(max_value);\n    }\n    compatible_numerical_types.to_numerical_type()\n}\n\nfn is_empty_after_merge(\n    merge_row_order: &MergeRowOrder,\n    column: &DynamicColumn,\n    columnar_ord: usize,\n) -> bool {\n    if column.num_values() == 0u32 {\n        // It was empty before the merge.\n        return true;\n    }\n    match merge_row_order {\n        MergeRowOrder::Stack(_) => {\n            // If we are stacking the columnar, no rows are being deleted.","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/columnar/src/columnar/merge/mod.rs#L325-L361","documentation":"merged_numerical_columns_type computes the numerical type resulting from merging several dynamic columns; min_max_if_numerical returns None for non-numerical columns and the code .expect()s, panicking with \"All columns re required to be numerical\". The contract is that callers (e.g. column_type_after_merge) only pass columns already known to be numerical (i64/u64/f64). If any column is Str/Bool/Bytes/etc., the precondition is violated and the process panics.","triggerScenarios":"Calling column_type_after_merge / merged_numerical_columns_type over an iterator containing at least one non-numerical DynamicColumn, e.g. merging columnar field data where some columns for a logical field are Str while others are numeric.","commonSituations":"Merging segments or columnar fields whose type drifted (schema-less columnar ingestion writing mixed types under one field name); a bug where the caller forgot to filter to numerical columns before this function.","solutions":["Fix the caller to filter/min_max_if_numerical-check first, merging only columns where min_max_if_numerical returns Some.","Ensure all writers to a given field emit the same column type; fix ingestion so a field never mixes Str and numeric columns.","If a mixed merge is legitimately possible, replace the expect with a fallback (e.g. skip non-numerical or return an error) in merged_numerical_columns_type.","Re-build/re-write the affected columnar field with a consistent type before merging."],"exampleFix":"// before\nlet numerical_type = merged_numerical_columns_type(all_columns.iter());\n// after\nlet numerical_cols = all_columns.iter().filter(|c| min_max_if_numerical(c).is_some());\nlet numerical_type = merged_numerical_columns_type(numerical_cols);","handlingStrategy":"type-guard","validationCode":"// Filter to numerical columns before merging types\nlet numerical_columns: Vec<&DynamicColumn> = columns\n    .iter()\n    .filter(|c| matches!(c.type_(), ColumnType::I64 | ColumnType::U64 | ColumnType::F64))\n    .collect();\nif numerical_columns.is_empty() { return Err(/* no numerical columns */); }","typeGuard":"fn is_numerical(col: &DynamicColumn) -> bool {\n    matches!(col.type_(), ColumnType::I64 | ColumnType::U64 | ColumnType::F64)\n}","tryCatchPattern":null,"preventionTips":["Enforce one column type per field at ingestion","Filter with min_max_if_numerical before computing merged types","Add schema checks when merging segments from different writers","Write merge tests with mixed-type fixtures"],"tags":["rust","panic","columnar","merge","type-mismatch"],"backgroundTag":"column-type-mismatch","analyzedSha":"b5d8deb80c26924e6b007a5b1a7630f35ca64de4","analyzedAt":"2026-09-05T13:20:51.521Z","contentChangedAt":"2026-09-05T13:20:51.521Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}