pola-rs/polars · error

out-of-range date

Error message

out-of-range date

What it means

Panics inside date32_to_date when NaiveDate::from_num_days_from_ce_opt(EPOCH_DAYS_FROM_CE + days) returns None, i.e. the i32 day count falls outside chrono NaiveDate's representable span (about years -262144..262143). The infallible wrapper uses .expect('out-of-range date') so out-of-range physical values abort rather than yield null.

Source

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

}

/// converts a `i32` representing a `date32` to [`NaiveDateTime`]
#[inline]
pub fn date32_to_datetime(v: i32) -> NaiveDateTime {
    date32_to_datetime_opt(v).expect("invalid or out-of-range datetime")
}

/// converts a `i32` representing a `date32` to [`NaiveDateTime`]
#[inline]
pub fn date32_to_datetime_opt(v: i32) -> Option<NaiveDateTime> {
    let delta = TimeDelta::try_days(v.into())?;
    unix_epoch().checked_add_signed(delta)
}

/// converts a `i32` representing a `date32` to [`NaiveDate`]
#[inline]
pub fn date32_to_date(days: i32) -> NaiveDate {
    date32_to_date_opt(days).expect("out-of-range date")
}

/// converts a `i32` representing a `date32` to [`NaiveDate`]
#[inline]
pub fn date32_to_date_opt(days: i32) -> Option<NaiveDate> {
    NaiveDate::from_num_days_from_ce_opt(EPOCH_DAYS_FROM_CE + days)
}

/// 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]

View on GitHub (pinned to df599052da)

Solutions

  1. Use date32_to_date_opt(days) and handle None (null/skip)
  2. Validate day counts against chrono's range before conversion
  3. Fix the upstream unit mismatch that put non-day values in the column
  4. Use Polars-level casts with strict=False so bad values become null

Example fix

// before
let d = date32_to_date(days); // panics for out-of-range days

// after
let d = date32_to_date_opt(days); // Option<NaiveDate>
let d = d.unwrap_or_default(); // or propagate as null
Defensive patterns

Strategy: validation

Validate before calling

use polars_arrow::temporal_conversions::date32_to_date_opt;

if date32_to_date_opt(days).is_none() {
    // treat as null / corrupt value
}

Type guard

fn date32_in_chrono_range(days: i32) -> bool {
    polars_arrow::temporal_conversions::date32_to_date_opt(days).is_some()
}

Prevention

When it happens

Trigger: Converting a Date array to calendar dates when it holds sentinel or corrupt values (i32::MIN, i32::MAX) - common when a millisecond-epoch column was misdeclared as date32.

Common situations: Schema drift between writer and reader; corrupt parquet/IPC sources; uninitialized buffers read as dates; fuzzed inputs.

Related errors


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