{"record":{"id":"f43e5b233510f8d7","repo":"influxdata/influxdb","slug":"no-rows-to-serialise","errorCode":null,"errorMessage":"no rows to serialise","messagePattern":"no rows to serialise","errorType":"error_code","errorClass":"CodecError","httpStatus":null,"severity":"error","filePath":"core/parquet_file/src/serialize.rs","lineNumber":65,"sourceCode":"/// ensure read and write work well together\nconst _: () = assert!(ROW_GROUP_WRITE_SIZE.is_multiple_of(BATCH_SIZE));\n\n/// [`RecordBatch`] to Parquet serialisation errors.\n///\n/// [`RecordBatch`]: arrow::record_batch::RecordBatch\n#[derive(Debug, Error)]\npub enum CodecError {\n    /// The result stream contained no batches.\n    #[error(\"no record batches to convert\")]\n    NoRecordBatches,\n\n    /// The result stream contained at least one [`RecordBatch`] and all\n    /// instances yielded by the stream contained 0 rows.\n    ///\n    /// This would result in an empty file being uploaded to object store.\n    ///\n    /// [`RecordBatch`]: arrow::record_batch::RecordBatch\n    #[error(\"no rows to serialise\")]\n    NoRows,\n\n    /// A DataFusion error during the plan execution.\n    ///\n    /// Of note: a ResourcesExhaused error likely means the buffer\n    /// used for parquet data became too large.\n    #[error(transparent)]\n    DataFusion(Box<DataFusionError>),\n\n    /// Serialising the [`IoxMetadata`] to protobuf-encoded bytes failed.\n    #[error(\"failed to serialize iox metadata: {0}\")]\n    MetadataSerialisation(#[from] prost::EncodeError),\n\n    /// Writing the parquet file failed with the specified error.\n    #[error(\"failed to build parquet file: {0}\")]\n    Writer(#[from] ParquetError),\n\n    /// Attempting to clone a handle to the provided write sink failed.","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/core/parquet_file/src/serialize.rs#L47-L83","documentation":"CodecError::NoRows, raised when the result stream produced at least one RecordBatch but every batch contained zero rows. Writing this would upload an empty Parquet file to object storage, so the library rejects it. Distinguishes 'no batches' (152) from 'batches exist but all empty'.","triggerScenarios":"A DataFusion plan yields batches with schema but 0 rows (common with projection/limit/filter nodes) and the stream is handed to the Parquet codec.","commonSituations":"Queries matching no rows where the executor still emits empty batches (e.g. after a filter on an empty partition), time-range predicates covering no data, or dedup/limit logic draining all rows.","solutions":["Count total rows across batches before serialising and skip the write/upload when the count is zero","Investigate why the query returns zero rows (predicate bounds, partition pruning)","Compact or drop empty data upstream so empty batches never reach the serialiser","If empty files are valid for your workflow, handle this variant explicitly and bypass the upload"],"exampleFix":"// before\nlet rows: usize = batches.iter().map(|b| b.num_rows()).sum();\nwrite_parquet(batches.into_iter())?; // fails with NoRows when rows == 0\n// after\nlet rows: usize = batches.iter().map(|b| b.num_rows()).sum();\nif rows == 0 { return Ok(None); }\nwrite_parquet(batches.into_iter())?;","handlingStrategy":"validation","validationCode":"let rows: usize = batches.iter().map(|b| b.num_rows()).sum();\nif rows == 0 {\n    return Ok(None); // all batches were empty\n}","typeGuard":null,"tryCatchPattern":"match res {\n    Err(CodecError::NoRows) => info!(\"query produced 0 rows; skipping empty file upload\"),\n    other => other?,\n}","preventionTips":["Sum num_rows across batches before writing, not just batch count","Filter out zero-row batches early in the pipeline","Alert on persist paths that receive all-empty streams — often a predicate bug"],"tags":["parquet","empty-input","zero-rows","serialization"],"backgroundTag":"empty-result-set","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}