influxdata/influxdb · error
no min time statistic
Error message
no min time statistic
What it means
After finding the time column, derive_min_max_time matches Statistics::I64(stats) and unwraps stats.min.expect("no min time statistic") (and max on the next line). Parquet column statistics are optional: writers can disable them, and an all-null column has no min/max. When the time column exists but its statistics carry no min, this expect panics.
Source
Thrown at core/parquet_file/src/metadata.rs:577
/// 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.
///
/// This can be used to store metadata separate from the related payload data. The usage of [Apache Thrift] allows the
/// same stability guarantees as the usage of an ordinary [Apache Parquet] file. To encode a thrift message into bytes
/// the [Thrift Compact Protocol] is used.
///
/// [Apache Parquet]: https://parquet.apache.org/
/// [Apache Thrift]: https://thrift.apache.org/
/// [Thrift Compact Protocol]: https://github.com/apache/thrift/blob/master/doc/specs/thrift-compact-protocol.mdView on GitHub (pinned to d28e26e048)
Solutions
- Re-write the file with column statistics enabled (arrow-rs/parquet writer default enables them).
- If calling derive_min_max_time directly, pre-check the time summary's stats have min/max Some before calling, and skip or compute from data otherwise.
- Validate files coming from external sources with a parquet-inspection step (footer statistics present for the time column) before cataloging.
- For genuinely empty time columns, write at least one row or handle the empty-range case in your tooling before IOx paths see the file.
Example fix
// before
let range = derive_min_max_time(stats);
// after
let time = stats.iter().find(|v| v.name == TIME_COLUMN_NAME);
match time.map(|t| &t.stats) {
Some(Statistics::I64(s)) if s.min.is_some() && s.max.is_some() => {
let range = derive_min_max_time(stats);
// ...
}
_ => return Err("time column lacks min/max statistics".into()),
} Defensive patterns
Strategy: validation
Validate before calling
// verify min/max statistics exist for the time column before deriving the range
fn time_stats_complete(stats: &[ColumnSummary]) -> bool {
stats.iter().any(|v| {
v.name == TIME_COLUMN_NAME
&& matches!(&v.stats, Statistics::I64(s) if s.min.is_some() && s.max.is_some())
})
}
if !time_stats_complete(&stats) {
return Err("time column lacks min/max statistics (writer omitted them?)".into());
} Try / catch
let range = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
derive_min_max_time(stats.clone())
}));
if let Err(_) = range {
return Err(CatalogError::IncompleteTimeStatistics.into());
} Prevention
- Write parquet with statistics enabled (avoid parquet statistics_enabled=false).
- Screen external files for footer statistics on the time column before cataloging.
- Handle all-null/empty time columns upstream (reject or populate) rather than letting derive_min_max_time see them.
- Add unit fixtures covering the no-min-statistics shape so tooling fails gracefully in tests, not prod.
When it happens
Trigger: to_parquet_file / derive_min_max_time on a file whose time-column chunk statistics were not written — writer configured with statistics disabled, a null-only time column, or a writer version that omits min/max for some encodings.
Common situations: Externally generated parquet written with parquet.statistics_enabled=false; empty or all-null test batches; files written by old/limited parquet writers that skip min/max for int64 columns.
Related errors
- invalid statistics
- no time column in metadata statistics
- invalid IOx metadata
- failed to read encoded schema
- num_row_groups_in_parallel should be above zero
AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16).
Data as JSON: /api/errors/3e8b788e6a9a0af1.
Report an issue: GitHub.