influxdata/influxdb · error
time column
Error message
time column
What it means
filter_time unwraps batch.time_column() with the message 'time column'. IOx batches are invariantly required to carry a non-nullable time column, so its absence is a programming error and the library panics rather than returning an error.
Solutions
- Ensure the batch always contains the time column before filtering
- Check the code path that produced the batch for a dropped/renamed time column
- In tests, use the batch builders that include the time column
Example fix
// before let out = filter_ranges(&batch, &[0..10], |t| t > 0); // after assert!(batch.time_column().is_some(), "batch missing time column"); let out = filter_ranges(&batch, &[0..10], |t| t > 0);
Defensive patterns
Strategy: type-guard
Validate before calling
if batch.time_column().is_none() { return Err("batch missing time column"); } Type guard
fn has_time_column(batch: &RecordBatch) -> bool { batch.time_column().is_some() } Prevention
- Treat the time column as an invariant of every batch entering the filter pipeline
- Add debug assertions in batch constructors
When it happens
Trigger: Calling filter_time (via filter_ranges/filter_batch) on a RecordBatch that has no time column, e.g. a batch built manually without it or with the time column dropped.
Common situations: Test helpers constructing batches from only tag/field columns; upstream pipeline bug dropping the time column before filtering.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- no time column in metadata statistics
- By the point that we're doing partitioning, we should've…
- Existing transaction for table should not exist
- mapped to out-of-bounds shard
- ordered catalog batch should contain changes
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/89b3e45f9aa5e41b.
Report an issue: GitHub.
Appendix: source
Thrown at core/partition/src/filter.rs:23
use crate::Batch;
use mutable_batch::MutableBatch;
use std::ops::Range;
/// Given a [`MutableBatch`] a time predicate and a set of row ranges, returns the row
/// indexes that pass the predicate
///
/// # Panic
///
/// Panics if `batch` does not contain a time column of the correct type
pub(crate) fn filter_time<'a, F>(
batch: &'a MutableBatch,
ranges: &'a [Range<usize>],
mut predicate: F,
) -> Vec<Range<usize>>
where
F: FnMut(i64) -> bool,
{
let col_data = batch.time_column().expect("time column");
// Time column is not nullable so can skip checking mask
let mut ret = vec![];
for range in ranges {
let offset = range.start;
ret.extend(
filter_slice(&col_data[range.clone()], &mut predicate)
.map(|r| (r.start + offset)..(r.end + offset)),
)
}
ret
}
fn filter_slice<'a, T, F>(
col_data: &'a [T],
predicate: &'a mut F,
) -> impl Iterator<Item = Range<usize>> + 'a
whereView on GitHub (pinned to 06200ef96b)