influxdata/influxdb · error · Error::NullTime
time column must not contain nulls
Error message
time column must not contain nulls
What it means
NullTimeSnafu is raised by write_table_batch in mutable_batch_pb when the batch's `time` column carries a non-null validity mask — i.e. some rows have null timestamps. IOx requires every row to have a concrete timestamp, so the decoder ensures valid_mask.is_none() for the Timestamp column before writing values via write_time_from_slice.
Solutions
- Make the producer populate a timestamp for every row so the time column has no null mask (or an all-valid mask)
- Drop rows with null timestamps before sending the batch
- If the null mask is spurious (all values valid), fix the serializer to emit an empty/all-true mask
Example fix
// before // time column null_mask with a false bit for row 2 // after // either fill the timestamp or filter the row let rows: Vec<_> = rows.into_iter().filter(|r| r.time.is_some()).collect();
Defensive patterns
Strategy: validation
Validate before calling
fn time_column_has_nulls(null_mask: &[bool]) -> bool {
null_mask.iter().any(|v| !v)
}
if time_column_has_nulls(&time_null_mask) { /* drop offending rows before sending */ } Try / catch
match write_table_batch(batch, table_batch) {
Err(e) if e.to_string() == "time column must not contain nulls" => /* filter null-timestamp rows and retry */,
other => other?,
} Prevention
- Require a timestamp on every row in producers
- Filter rows with missing timestamps upstream
- Never emit a null mask for the time column from serializers
When it happens
Trigger: Calling write_table_batch / decode_database_batch where the time column's null_mask has any false bits (null timestamps), typically because a row's timestamp field was missing or set to null in the protobuf.
Common situations: Producers sending rows without timestamps relying on server defaults; upstream ETL that writes optional timestamps as nulls; a serializer bug emitting a null mask for the time column even when all values exist.
Related errors
- duplicate column name
- table batch must contain time column
- Error converting compaction level
- Error converting max_columns_per_table
- Error converting max_tables
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/923e20a97763ea30.
Report an issue: GitHub.
Appendix: source
Thrown at core/mutable_batch_pb/src/decode.rs:217
&column.column_name,
valid_mask,
RepeatLastElement::new(packed_strings_iter(packed)),
)
} else {
writer.write_string(
&column.column_name,
valid_mask,
RepeatLastElement::new(values.string_values.iter().map(|x| x.as_str())),
)
}
}
InfluxColumnType::Field(InfluxFieldType::Boolean) => writer.write_bool(
&column.column_name,
valid_mask,
RepeatLastElement::new(values.bool_values.iter().cloned()),
),
InfluxColumnType::Timestamp => {
ensure!(valid_mask.is_none(), NullTimeSnafu);
writer.write_time_from_slice(&column.column_name, &values.i64_values)
}
}
.context(WriteSnafu {
column: &column.column_name,
})?;
}
writer.commit();
Ok(())
}
/// Iterator wrapper that repeats the last element forever.
///
/// This will just yield `None` if the wrapped iterator was empty.
struct RepeatLastElement<I>
where
I: Iterator,View on GitHub (pinned to 06200ef96b)