SeaQL/sea-orm · error

Failed to get datetime

Error message

Failed to get datetime

What it means

This panic comes from an `expect("Failed to get datetime")` inside ProxyRow's MySQL driver conversion. When the column's declared type is DATETIME, the driver calls `row.try_get::<Option<chrono::NaiveDateTime>, _>()` and panics if sqlx cannot decode the raw value into that Rust type. It means the database returned a DATETIME column whose underlying value does not satisfy sqlx's decode requirements (wrong sqlx type, zero-date, or a format the decoder rejects).

Source

Thrown at sea-orm-sync/src/driver/sqlx_mysql.rs:485

                        ),

                        #[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. Enable MySQL strict mode / set `sql_mode` to reject zero dates and clean or migrate rows containing '0000-00-00 00:00:00'.
  2. Verify the column is a genuine MySQL DATETIME (`SHOW COLUMNS FROM ...`) and not a drifted/aliased type; fix the schema or cast in the query.
  3. Use a MariaDB-compatible sqlx driver setting or upgrade sqlx if connecting to MariaDB with known DATETIME encoding differences.
  4. Prefer `try_get` with proper error propagation instead of `.expect(...)` in the driver code so decode failures become normal errors (upstream fix in src/ then regenerate sea-orm-sync).

Example fix

// before: query hits a legacy zero-date row and panics
let rows = proxy.query_all(statement)?;

// after: sanitize data server-side first
-- ALTER TABLE t MODIFY col DATETIME NULL;
-- UPDATE t SET col = NULL WHERE col = '0000-00-00 00:00:00';
Defensive patterns

Strategy: validation

Validate before calling

// Sanitize zero/invalid DATETIME rows before querying
-- SELECT COUNT(*) FROM t WHERE col = '0000-00-00 00:00:00' OR col IS NULL; -- must be 0
-- Ensure sql_mode includes NO_ZERO_DATE/STRICT_TRANS_TABLES:
-- SELECT @@sql_mode;

Try / catch

// The panic is not catchable as a DbErr; avoid it by pre-validating data.
// Optionally isolate risky reads and check column types first:
let cols = db.query_all(Statement::from_string(
    DatabaseBackend::MySql,
    format!("SHOW COLUMNS FROM {}", table),
))?; // verify type == "datetime" and no legacy values
let rows = db.query_all(statement)?;

Prevention

When it happens

Trigger: Executing a query via the sync proxy against MySQL where a column typed DATETIME contains a value sqlx cannot decode into `chrono::NaiveDateTime` — e.g. MySQL's zero date '0000-00-00 00:00:00', an invalid/NULL-encoded value in a NOT NULL branch, or a column reported as DATETIME but holding a different wire type. The panic occurs inside `crate::ProxyRow` while converting the raw sqlx row into SeaORM Values.

Common situations: Connecting to a MySQL/MariaDB server with `NO_ZERO_DATE` not enforced (legacy data with zero dates); MariaDB versions that encode DATETIME differently than MySQL; schema drift where a column was ALTERed to DATETIME but holds legacy values; using sqlx's MySQL driver against a proxy or non-MySQL backend that misreports column types.

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/cb1df1f597588a2c. Report an issue: GitHub.