{"record":{"id":"f3045e836a6a2bfe","repo":"quickwit-oss/quickwit","slug":"no-inputs-to-align","errorCode":null,"errorMessage":"no inputs to align","messagePattern":"no inputs to align","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-parquet-engine/src/merge/schema.rs","lineNumber":59,"sourceCode":"/// Returns the union schema and a vector of batches where every batch has\n/// exactly the same schema. Missing columns are filled with null arrays.\n///\n/// The union schema uses plain types for internal alignment: all string-like\n/// types (Utf8, LargeUtf8, Dictionary) are normalized to Utf8 so that\n/// `take` works uniformly across concatenated inputs. The actual output\n/// file types are determined later by [`optimize_output_batch`] based on\n/// each output file's data characteristics.\n///\n/// Columns are ordered in \"Husky order\":\n/// 1. Sort schema columns (in configured order)\n/// 2. `sorted_series` column\n/// 3. Remaining columns in alphabetical order\npub fn align_inputs_to_union_schema(\n    inputs: &[RecordBatch],\n    sort_fields_str: &str,\n) -> Result<(SchemaRef, Vec<RecordBatch>)> {\n    if inputs.is_empty() {\n        bail!(\"no inputs to align\");\n    }\n\n    // Track each field's normalized type, whether any input declared\n    // it nullable, and how many of the input batches contain it. The\n    // union field is nullable iff some input observed it as nullable\n    // OR some input is missing the field entirely (a row from a\n    // missing-the-field input will be null in the merged output).\n    // The previous version always defaulted new fields to nullable on\n    // first sight, which broke columns whose nullability must be\n    // preserved (e.g. `List<Float64>` — the writer's non-nullable-\n    // list contract requires the union field to stay non-nullable).\n    struct FieldInfo {\n        normalized_type: DataType,\n        any_nullable: bool,\n        appears_in: usize,\n    }\n    let mut field_map: BTreeMap<String, FieldInfo> = BTreeMap::new();\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-parquet-engine/src/merge/schema.rs#L41-L77","documentation":"align_inputs_to_union_schema computes the union schema of all input RecordBatches and aligns each batch to it. With zero inputs there is no schema to derive, so the function rejects the empty slice outright instead of returning a meaningless empty result.","triggerScenarios":"Calling align_inputs_to_union_schema with an empty `&[RecordBatch]` — e.g. a region or split produced no batches, or upstream filtering removed every batch before alignment.","commonSituations":"Merging splits that turn out to contain zero rows after decoding; a caller that skips the is_empty check when collecting batches per region; pipeline stages that pass through empty vecs from upstream producers.","solutions":["Check inputs.is_empty() at the call site and return early (no output file) instead of invoking alignment.","Ensure split/region producers never emit an empty batch list, or that empty regions are skipped upstream.","If an empty merge is legitimate for your flow, handle it before calling align and emit an empty MergeOutputFile yourself if required."],"exampleFix":"// before\nlet (schema, aligned) = align_inputs_to_union_schema(&batches, &sort)?;\n// after\nif batches.is_empty() {\n    return Ok(None); // nothing to merge for this region\n}\nlet (schema, aligned) = align_inputs_to_union_schema(&batches, &sort)?;","handlingStrategy":"validation","validationCode":"if batches.is_empty() { return Ok(None); } // skip alignment for empty regions","typeGuard":null,"tryCatchPattern":"match align_inputs_to_union_schema(&batches, &sort) {\n    Err(e) if e.to_string() == \"no inputs to align\" => Ok(Vec::new()),\n    other => other.map(|_| ()),\n}","preventionTips":["Filter out empty regions/splits before the alignment stage.","Ensure batch collectors never emit empty vecs downstream.","Unit-test the merge pipeline with zero-row splits."],"tags":["arrow","schema","empty-input"],"backgroundTag":"empty-required-field","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}