SeaQL/sea-orm · error

Failed to get year

Error message

Failed to get year

What it means

ProxyRow maps MySQL YEAR columns to a date Value and calls `row.try_get::<Option<chrono::NaiveDate>, _>()` with `expect("Failed to get year")`. This panics when sqlx cannot decode the YEAR column's value into `chrono::NaiveDate`. It indicates the raw value of a column reported as YEAR does not meet decode expectations (e.g. it arrives as an integer or string rather than a date).

Source

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

                        ),

                        #[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())
                                .expect("Failed to get year")
                                .map(Box::new),
                        ),

                        "ENUM" | "SET" | "GEOMETRY" => Value::String(
                            row.try_get::<Option<String>, _>(c.ordinal())
                                .expect("Failed to get serialized string")
                                .map(Box::new),
                        ),

                        #[cfg(feature = "with-bigdecimal")]
                        "DECIMAL" => Value::BigDecimal(
                            row.try_get::<Option<bigdecimal::BigDecimal>, _>(c.ordinal())

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Change the column type from YEAR to SMALLINT or DATE in the schema; YEAR is rarely worth its compatibility pitfalls.
  2. Select with an explicit cast: `SELECT CAST(year_col AS DATE) FROM ...` or `CAST(year_col AS CHAR)` so the driver decodes a type it supports.
  3. Upgrade/downgrade sqlx to a version with correct MySQL YEAR decoding, or file/check upstream sqlx issues for YEAR support.
  4. Replace `.expect(...)` with error propagation in src/ (then run build-tools/make-sync.sh) so the failure becomes a `DbErr` instead of a panic.

Example fix

// before: SELECT year_col FROM t;  -> panic in ProxyRow
// after: cast in SQL so sqlx sees a supported type
let stmt = Statement::from_string(
    DatabaseBackend::MySql,
    "SELECT CAST(year_col AS CHAR) AS year_col FROM t",
);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the column isn't MySQL YEAR before binding to NaiveDate decoding:
-- SHOW COLUMNS FROM t LIKE 'year_col'; -- prefer SMALLINT/DATE over YEAR
-- Or cast at query time: SELECT CAST(year_col AS CHAR) AS year_col FROM t;

Try / catch

// YEAR decode panics aren't DbErr; cast columns in SQL instead:
let stmt = Statement::from_string(
    DatabaseBackend::MySql,
    "SELECT CAST(year_col AS CHAR) AS year_col FROM t",
);
let rows = db.query_all(stmt)?;

Prevention

When it happens

Trigger: A query against MySQL returns a YEAR column and sqlx fails to decode it as `chrono::NaiveDate` — commonly because the MySQL YEAR type is delivered over the wire as a 2-byte/integer value or short string ('2024') rather than a full date the NaiveDateTime/NaiveDate decoder accepts.

Common situations: Tables using MySQL's YEAR type (rare but real in legacy schemas); sqlx versions where YEAR decoding to NaiveDate is unsupported or broken; MariaDB returning YEAR with different wire encoding.

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