pola-rs/polars · error

out-of-range in duration conversion

Error message

out-of-range in duration conversion

What it means

Panics inside duration_ms_to_duration: Duration::try_milliseconds returns None when the i64 millisecond count exceeds chrono Duration's hard cap of i64::MAX milliseconds (itself the result of internal seconds-to-ms scaling), and the wrapper .expect panics.

Source

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

    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)
}

/// converts a `i64` representing a `duration(ns)` to [`Duration`]
#[inline]
pub fn duration_ns_to_duration(v: i64) -> Duration {
    Duration::nanoseconds(v)
}

/// converts a `i32` representing a `time32(ms)` to [`NaiveTime`]
#[inline]
pub fn time32ms_to_time(v: i32) -> NaiveTime {
    let v = v as i64;

View on GitHub (pinned to df599052da)

Solutions

  1. Range-check the value (|v| must fit comfortably in i64 ms, effectively |v| < i64::MAX) and null out extremes
  2. Use Duration::try_milliseconds(v) directly and handle the Option
  3. Fix the upstream unit error
  4. Sanitize sentinel values before conversion

Example fix

// before
let d = duration_ms_to_duration(v); // panics on overflow

// after
let d = Duration::try_milliseconds(v)
    .unwrap_or_default(); // or map to null
Defensive patterns

Strategy: validation

Validate before calling

fn duration_ms_valid(v: i64) -> bool {
    Duration::try_milliseconds(v).is_some()
}

Type guard

fn is_valid_duration_ms(v: i64) -> bool {
    chrono::Duration::try_milliseconds(v).is_some()
}

Prevention

When it happens

Trigger: Converting duration(ms) values at extreme magnitude - i64::MIN/MAX sentinels or wrong-unit data (e.g. nanosecond values in a millisecond column near overflow).

Common situations: Unit mismatches in arrow duration producers; garbage numeric data; uninitialized i64 memory interpreted as durations.

Related errors


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