{"record":{"id":"117d97bd50d63a2f","repo":"quickwit-oss/quickwit","slug":"num-outputs-must-be-at-least-1-117d97","errorCode":null,"errorMessage":"num_outputs must be at least 1","messagePattern":"num_outputs must be at least 1","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-parquet-engine/src/merge/streaming.rs","lineNumber":157,"sourceCode":"pub(crate) fn record_body_col_page_cache_len(_len: usize) {}\n\n/// Streaming N-input → M-output column-major merge.\n///\n/// See module docs for the four phases. Returns one\n/// [`MergeOutputFile`] per output file produced (zero-row outputs are\n/// dropped). Caller's `config.num_outputs` is the upper bound on the\n/// number of files; fewer are returned when there are not enough\n/// `sorted_series` transitions to split at.\npub async fn streaming_merge_sorted_parquet_files(\n    inputs: Vec<Box<dyn ColumnPageStream>>,\n    output_dir: &Path,\n    config: &MergeConfig,\n) -> Result<Vec<MergeOutputFile>> {\n    if inputs.is_empty() {\n        bail!(\"merge requires at least one input\");\n    }\n    if config.num_outputs == 0 {\n        bail!(\"num_outputs must be at least 1\");\n    }\n\n    let input_meta = extract_and_validate_input_metadata(&inputs)?;\n\n    // Reject legacy multi-RG inputs (`rg_partition_prefix_len == 0`\n    // AND any input has >1 row group). These have no alignment claim,\n    // so RG boundaries are arbitrary row counts that may split a\n    // single sort-key value across two RGs. The streaming engine\n    // cannot determine merge regions without column-chunk-bounded\n    // buffering; such inputs must go through `LegacyInputAdapter`\n    // (from PR-5, see `storage::legacy_adapter`), which presents\n    // them as one synthetic single-RG stream.\n    //\n    // This guard catches caller bugs — production code always routes\n    // legacy splits through the adapter (see `merge::execute_merge_operation`\n    // in `merge/mod.rs`), so a raw legacy `StreamingParquetReader`\n    // arriving here is a wiring mistake, not a supported input shape.\n    // Bail with a clear pointer rather than wading further into the","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-parquet-engine/src/merge/streaming.rs#L139-L175","documentation":"MergeConfig.num_outputs controls how many output files the streaming merge produces; a value of 0 is meaningless (at least one output or none at all is expected via a different path), so the merger rejects it up front. Valid configurations use num_outputs >= 1.","triggerScenarios":"Calling streaming_merge_sorted_parquet_files with a MergeConfig where num_outputs == 0, typically from a default-built or partially initialized MergeConfig.","commonSituations":"Config parsing that leaves num_outputs unset (defaulting to 0); a caller computing num_outputs from a formula that returns 0 when no outputs were requested.","solutions":["Set config.num_outputs to at least 1 before invoking the merge.","Fix MergeConfig construction/deserialization to default num_outputs to 1 instead of 0.","If zero outputs is the intent, skip the merge call entirely rather than passing num_outputs = 0."],"exampleFix":"// before\nlet config = MergeConfig { num_outputs: 0, ..Default::default() };\n// after\nlet config = MergeConfig { num_outputs: 1, ..Default::default() };","handlingStrategy":"validation","validationCode":"anyhow::ensure!(config.num_outputs >= 1, \"MergeConfig.num_outputs must be >= 1 before merging\");","typeGuard":null,"tryCatchPattern":"match streaming_merge_sorted_parquet_files(streams, &out, &cfg).await {\n    Err(e) if e.to_string().contains(\"num_outputs must be at least 1\") => {\n        let cfg = MergeConfig { num_outputs: 1, ..cfg.clone() };\n        streaming_merge_sorted_parquet_files(streams, &out, &cfg).await\n    }\n    other => other,\n}","preventionTips":["Default num_outputs to 1 in MergeConfig::default and deserialization.","Validate MergeConfig at construction, not deep in the pipeline.","Never compute num_outputs with formulas that can yield 0 without an early return."],"tags":["merge","config","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}