pola-rs/polars · error
Invalid time unit '{tu:?}' for Datetime.
Error message
Invalid time unit '{tu:?}' for Datetime. What it means
The JSON writer maps naive Timestamp columns to chrono converters only for Nanosecond, Microsecond and Millisecond units. Timestamp(TimeUnit::Second, None) - legal in Arrow and typical of arrow-rs interop - falls through to the catch-all panic. Second-with-tz goes down timestamp_tz_serializer instead, so this is specifically the naive path.
Source
Thrown at crates/polars-json/src/json/write/serialize.rs:591
dictionary_utf8view_serializer::<u32>(array, offset, take)
},
_ => {
// Not produced by polars
unreachable!()
},
},
ArrowDataType::Date32 => date_serializer(
array.as_any().downcast_ref().unwrap(),
date32_to_date,
offset,
take,
),
ArrowDataType::Timestamp(tu, None) => {
let convert = match tu {
TimeUnit::Nanosecond => timestamp_ns_to_datetime,
TimeUnit::Microsecond => timestamp_us_to_datetime,
TimeUnit::Millisecond => timestamp_ms_to_datetime,
tu => panic!("Invalid time unit '{tu:?}' for Datetime."),
};
timestamp_serializer(
array.as_any().downcast_ref().unwrap(),
convert,
offset,
take,
)
},
ArrowDataType::Timestamp(time_unit, Some(tz)) => timestamp_tz_serializer(
array.as_any().downcast_ref().unwrap(),
*time_unit,
tz,
offset,
take,
),
ArrowDataType::Duration(tu) => {
let convert = match tu {
TimeUnit::Nanosecond => duration_ns_to_duration,View on GitHub (pinned to 9b5d73fd00)
Solutions
- Cast to a supported unit before writing: df.cast / with_column(col("ts").cast(&DataType::Datetime(TimeUnit::Microseconds, None)))
- If building arrays yourself, encode timestamps in us/ms/ns rather than s
- Inspect dtypes (schema) before write_json and normalize units
Example fix
// before: column typed Timestamp(Second, None)
df.write_json(&mut out)?; // panic: Invalid time unit 'Second' for Datetime.
// after
let df = df.with_column(col("ts").cast(&DataType::Datetime(TimeUnit::Microseconds, None)))?;
df.write_json(&mut out)?; Defensive patterns
Strategy: fallback
Validate before calling
fn normalize_timestamp_units(df: &DataFrame) -> PolarsResult<DataFrame> {
let mut exprs = vec![];
for (name, dt) in df.schema().iter() {
if matches!(dt, DataType::Datetime(TimeUnit::Seconds, _)) {
exprs.push(col(name).cast(&DataType::Datetime(TimeUnit::Microseconds, dt.time_zone().cloned())).alias(name));
}
}
df.lazy().with_columns(exprs).collect()
}
// run before write_json / JsonWriter::write Type guard
fn has_writable_timestamp_units(df: &DataFrame) -> bool {
df.schema().iter_values().all(|dt| match dt {
DataType::Datetime(tu, _) => !matches!(tu, TimeUnit::Seconds),
_ => true,
})
} Try / catch
catch_unwind(AssertUnwindSafe(|| df.write_json(&mut out))) to get a job-level error; casting Seconds -> Microseconds beforehand removes the failing branch entirely.
Prevention
- Cast Timestamp(Second) to us/ms/ns at every arrow interop boundary
- Assert on dtypes before JSON export in tests
- Document that polars' JSON writer supports only ns/us/ms timestamps
When it happens
Trigger: write_json on an Int64 array typed ArrowDataType::Timestamp(TimeUnit::Second, None): data converted from arrow-rs RecordBatches, IPC/Avro readers, or hand-built arrays using second-precision epoch values.
Common situations: arrow-rs/polars interop boundaries; datasets produced by systems that store epoch-seconds.
Related errors
- Invalid time unit '{tu:?}' for Duration.
- Invalid time unit '{tu:?}' for Time.
- Timezone {tz} is invalid or not supported
- Invalid Offset format (must be [-]00:00) or timezones featur
- not implemented
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/23c3bb98bea4ff48.
Report an issue: GitHub.