pola-rs/polars · error

invalid time

Error message

invalid time

What it means

Panics inside time32s_to_time: the i32 seconds value is cast with 'v as u32', so any negative value wraps to a huge u32, and NaiveTime::from_num_seconds_from_midnight_opt requires seconds < 86400. Any v < 0 or v >= 86400 therefore fails the .expect('invalid time').

Source

Thrown at crates/polars-arrow/src/temporal_conversions.rs:73

/// converts a `i64` representing a `date64` to [`NaiveDateTime`]
#[inline]
pub fn date64_to_datetime(v: i64) -> NaiveDateTime {
    TimeDelta::try_milliseconds(v)
        .and_then(|delta| unix_epoch().checked_add_signed(delta))
        .expect("invalid or out-of-range datetime")
}

/// converts a `i64` representing a `date64` to [`NaiveDate`]
#[inline]
pub fn date64_to_date(milliseconds: i64) -> NaiveDate {
    date64_to_datetime(milliseconds).date()
}

/// converts a `i32` representing a `time32(s)` to [`NaiveTime`]
#[inline]
pub fn time32s_to_time(v: i32) -> NaiveTime {
    NaiveTime::from_num_seconds_from_midnight_opt(v as u32, 0).expect("invalid time")
}

/// converts a `i64` representing a `duration(s)` to [`Duration`]
#[inline]
pub fn duration_s_to_duration(v: i64) -> Duration {
    Duration::try_seconds(v).expect("out-of-range duration")
}

/// converts a `i64` representing a `duration(ms)` to [`Duration`]
#[inline]
pub fn duration_ms_to_duration(v: i64) -> Duration {
    Duration::try_milliseconds(v).expect("out-of-range in duration conversion")
}

/// converts a `i64` representing a `duration(us)` to [`Duration`]
#[inline]
pub fn duration_us_to_duration(v: i64) -> Duration {
    Duration::microseconds(v)

View on GitHub (pinned to df599052da)

Solutions

  1. Range-check first: accept only 0 <= v < 86_400
  2. Null out or clamp invalid values before conversion
  3. Fix the unit mismatch upstream (ms vs s)
  4. Where possible use the Polars cast layer with strict=False to emit nulls

Example fix

// before
let t = time32s_to_time(v); // panics for v < 0 or v >= 86_400

// after
let t = (0..86_400).contains(&v)
    .then(|| time32s_to_time(v))
    .unwrap_or(NaiveTime::MIN); // or propagate null
Defensive patterns

Strategy: validation

Validate before calling

fn time32s_valid(v: i32) -> bool {
    (0..86_400).contains(&v) // seconds within one day
}

Type guard

fn is_valid_time32s(v: i32) -> bool {
    (0..86_400).contains(&v)
}

Prevention

When it happens

Trigger: Converting a time32(s) array containing negative values (sentinels, misparsed data) or values >= 86400 (overflow from unit mismatch, e.g. milliseconds stored in a seconds column).

Common situations: CSVs with '-1' defaults in time columns; ms-epoch-of-day values written into a time32(s) field; corrupt arrow data.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/830c91ce85a03a93. Report an issue: GitHub.