influxdata/influxdb · error

no time column in metadata statistics

Error message

no time column in metadata statistics

What it means

derive_min_max_time scans the ColumnSummary list for TIME_COLUMN_NAME ("time") and expects to find it ("no time column in metadata statistics"), then asserts its InfluxDbType is Timestamp. The IOx write path always emits a time column with IOx field-type metadata; parquet produced without that metadata (plain arrow/pandas writers, or RecordBatches serialized without the IOx schema) has either no 'time' column or one without IOx typing, so the find returns None and this expect panics. The doc comment on the function documents exactly this precondition.

Source

Thrown at core/parquet_file/src/metadata.rs:570

///
/// # Panics
///
/// This method panics if the [`IoxParquetMetaData`] structure does not
/// contain valid metadata bytes, has no readable schema, or has no field
/// statistics.
///
/// A [`RecordBatch`] serialized without the embedded metadata found in the
/// IOx [`Schema`] type will cause a statistic resolution failure due to
/// lack of the IOx field type metadata for the time column. Batches
/// produced from the through the IOx write path always include this
/// metadata.
///
/// [`RecordBatch`]: arrow::record_batch::RecordBatch
pub fn derive_min_max_time(stats: Vec<ColumnSummary>) -> TimestampRange {
    let time_summary = stats
        .into_iter()
        .find(|v| v.name == TIME_COLUMN_NAME)
        .expect("no time column in metadata statistics");

    assert_eq!(time_summary.influxdb_type, InfluxDbType::Timestamp);

    // Extract the min/max timestamps.
    match time_summary.stats {
        Statistics::I64(stats) => {
            let min = Timestamp::new(stats.min.expect("no min time statistic"));
            let max = Timestamp::new(stats.max.expect("no max time statistic"));
            TimestampRange { min, max }
        }
        _ => panic!("unexpected physical type for timestamp column"),
    }
}
/// Parquet metadata with IOx-specific wrapper.
#[derive(Clone, PartialEq, Eq)]
pub struct IoxParquetMetaData {
    /// [Apache Parquet] metadata as freestanding [Apache Thrift]-encoded, and [Zstandard]-compressed bytes.
    ///

View on GitHub (pinned to d28e26e048)

Solutions

  1. Write/rewrite the data through the IOx ingest path so the time column and its IOx timestamp typing exist.
  2. If invoking derive_min_max_time yourself, check stats.iter().any(|v| v.name == "time") first and handle the missing case.
  3. Verify upstream of to_parquet_file that the file carries IOx metadata (decode + read_schema succeed and contain a time field).
  4. Do not rename or project out the time column in preprocessing steps.

Example fix

// before
let range = derive_min_max_time(stats); // panics if no 'time' column

// after
if !stats.iter().any(|v| v.name == TIME_COLUMN_NAME) {
    return Err("parquet file has no IOx time column".into());
}
let range = derive_min_max_time(stats);
Defensive patterns

Strategy: validation

Validate before calling

// check for the IOx time column before deriving the time range
fn has_time_column(stats: &[ColumnSummary]) -> bool {
    stats.iter().any(|v| v.name == TIME_COLUMN_NAME)
}

if !has_time_column(&stats) {
    return Err("parquet file lacks the IOx time column".into());
}
let range = derive_min_max_time(stats.to_vec());

Try / catch

let range = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    derive_min_max_time(stats.clone())
}));
if let Err(_) = range {
    return Err(CatalogError::MissingTimeColumn.into());
}

Prevention

When it happens

Trigger: Calling to_parquet_file (or derive_min_max_time directly) with statistics derived from a RecordBatch/parquet file written outside the IOx write path — no column named 'time', or renamed time columns, or statistics computed from a schema lacking IOx field metadata.

Common situations: Loading externally written parquet into IOx catalog tooling; test fixtures created with vanilla arrow writers; data pipelines that rewrite IOx files and drop the IOx schema extension.

Related errors


AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16). Data as JSON: /api/errors/6b730a3410df474b. Report an issue: GitHub.