SeaQL/sea-orm · error

Failed to get datetime

Error message

Failed to get datetime

What it means

ProxyRow panicked while converting a MySQL DATETIME column with `with-chrono` enabled: `row.try_get::<Option<chrono::NaiveDateTime>, _>(c.ordinal())` errored and `.expect("Failed to get datetime")` panicked. sqlx could not decode the value as chrono::NaiveDateTime, so the value does not match the declared DATETIME type.

Source

Thrown at src/driver/sqlx_mysql.rs:493

                        ),

                        #[cfg(feature = "with-chrono")]
                        "TIME" => Value::ChronoTime(
                            row.try_get::<Option<chrono::NaiveTime>, _>(c.ordinal())
                                .expect("Failed to get time")
                                .map(Box::new),
                        ),
                        #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
                        "TIME" => Value::TimeTime(
                            row.try_get::<Option<time::Time>, _>(c.ordinal())
                                .expect("Failed to get time")
                                .map(Box::new),
                        ),

                        #[cfg(feature = "with-chrono")]
                        "DATETIME" => Value::ChronoDateTime(
                            row.try_get::<Option<chrono::NaiveDateTime>, _>(c.ordinal())
                                .expect("Failed to get datetime")
                                .map(Box::new),
                        ),
                        #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
                        "DATETIME" => Value::TimeDateTime(
                            row.try_get::<Option<time::PrimitiveDateTime>, _>(c.ordinal())
                                .expect("Failed to get datetime")
                                .map(Box::new),
                        ),

                        #[cfg(feature = "with-chrono")]
                        "YEAR" => Value::ChronoDate(
                            row.try_get::<Option<chrono::NaiveDate>, _>(c.ordinal())
                                .expect("Failed to get year")
                                .map(Box::new),
                        ),
                        #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
                        "YEAR" => Value::TimeDate(
                            row.try_get::<Option<time::Date>, _>(c.ordinal())

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Purge or NULL zero datetimes: UPDATE t SET dt = NULL WHERE dt = '0000-00-00 00:00:00'; enable strict SQL mode thereafter.
  2. NULLIF or CAST the offending expression in SQL so the wire value is a proper DATETIME.
  3. Confirm the effective column/expression type via information_schema or EXPLAIN, especially for views and UNIONs.
  4. Check that you are not inserting invalid values from your own writes; validate on the Rust side before insert.
  5. Upgrade sea-orm and sqlx together if decode strictness changed with a version bump.

Example fix

// before — zero datetime row panics ProxyRow
let orders = Order::find().all(db).await?;

// after — sanitize at query time
let orders = Order::find()
    .from_raw_sql(Statement::from_sql_and_values(
        DbBackend::MySql,
        "SELECT id, NULLIF(shipped_at, '0000-00-00 00:00:00') AS shipped_at FROM orders",
        [],
    ))
    .all(db).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight zero-datetime scan
// SELECT COUNT(*) FROM orders WHERE shipped_at = '0000-00-00 00:00:00'
if count_zero_datetimes(db, "orders", "shipped_at").await? > 0 {
    bail!("zero datetimes present; NULL them before querying");
}

Type guard

fn valid_mysql_datetime(s: &str) -> bool {
    s != "0000-00-00 00:00:00" && chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S").is_ok()
}

Try / catch

let dt = std::panic::catch_unwind(|| row.try_decode_datetime(ordinal)).ok().flatten();
let dt = dt.or_else(|| load_datetime_as_string_then_parse(ordinal));

Prevention

When it happens

Trigger: Reading a DATETIME column containing the zero datetime '0000-00-00 00:00:00', values outside chrono's supported range, or expressions (NOW(), DATE_SUB aliases) whose runtime type or format diverges from the declared DATETIME.

Common situations: Zero datetimes in legacy rows from non-strict servers; timezone-misconfigured servers returning stringified values; schema drift where a column was altered but cached metadata/stale prepared statements disagree.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10). Data as JSON: /api/errors/f04f1f646410d2e3. Report an issue: GitHub.