influxdata/influxdb · error · CodecError

no rows to serialise

Error message

no rows to serialise

What it means

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'.

Solutions

  1. Count total rows across batches before serialising and skip the write/upload when the count is zero
  2. Investigate why the query returns zero rows (predicate bounds, partition pruning)
  3. Compact or drop empty data upstream so empty batches never reach the serialiser
  4. If empty files are valid for your workflow, handle this variant explicitly and bypass the upload

Example fix

// before
let rows: usize = batches.iter().map(|b| b.num_rows()).sum();
write_parquet(batches.into_iter())?; // fails with NoRows when rows == 0
// after
let rows: usize = batches.iter().map(|b| b.num_rows()).sum();
if rows == 0 { return Ok(None); }
write_parquet(batches.into_iter())?;
Defensive patterns

Strategy: validation

Validate before calling

let rows: usize = batches.iter().map(|b| b.num_rows()).sum();
if rows == 0 {
    return Ok(None); // all batches were empty
}

Try / catch

match res {
    Err(CodecError::NoRows) => info!("query produced 0 rows; skipping empty file upload"),
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/f43e5b233510f8d7. Report an issue: GitHub.

Appendix: source

Thrown at core/parquet_file/src/serialize.rs:65

/// ensure read and write work well together
const _: () = assert!(ROW_GROUP_WRITE_SIZE.is_multiple_of(BATCH_SIZE));

/// [`RecordBatch`] to Parquet serialisation errors.
///
/// [`RecordBatch`]: arrow::record_batch::RecordBatch
#[derive(Debug, Error)]
pub enum CodecError {
    /// The result stream contained no batches.
    #[error("no record batches to convert")]
    NoRecordBatches,

    /// The result stream contained at least one [`RecordBatch`] and all
    /// instances yielded by the stream contained 0 rows.
    ///
    /// This would result in an empty file being uploaded to object store.
    ///
    /// [`RecordBatch`]: arrow::record_batch::RecordBatch
    #[error("no rows to serialise")]
    NoRows,

    /// A DataFusion error during the plan execution.
    ///
    /// Of note: a ResourcesExhaused error likely means the buffer
    /// used for parquet data became too large.
    #[error(transparent)]
    DataFusion(Box<DataFusionError>),

    /// Serialising the [`IoxMetadata`] to protobuf-encoded bytes failed.
    #[error("failed to serialize iox metadata: {0}")]
    MetadataSerialisation(#[from] prost::EncodeError),

    /// Writing the parquet file failed with the specified error.
    #[error("failed to build parquet file: {0}")]
    Writer(#[from] ParquetError),

    /// Attempting to clone a handle to the provided write sink failed.

View on GitHub (pinned to 06200ef96b)