{"record":{"id":"4d6e2c44f71fbcb1","repo":"SeaQL/sea-orm","slug":"failed-to-get-year-4d6e2c","errorCode":null,"errorMessage":"Failed to get year","messagePattern":"Failed to get year","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/driver/sqlx_mysql.rs","lineNumber":506,"sourceCode":"                        ),\n\n                        #[cfg(feature = \"with-chrono\")]\n                        \"DATETIME\" => Value::ChronoDateTime(\n                            row.try_get::<Option<chrono::NaiveDateTime>, _>(c.ordinal())\n                                .expect(\"Failed to get datetime\")\n                                .map(Box::new),\n                        ),\n                        #[cfg(all(feature = \"with-time\", not(feature = \"with-chrono\")))]\n                        \"DATETIME\" => Value::TimeDateTime(\n                            row.try_get::<Option<time::PrimitiveDateTime>, _>(c.ordinal())\n                                .expect(\"Failed to get datetime\")\n                                .map(Box::new),\n                        ),\n\n                        #[cfg(feature = \"with-chrono\")]\n                        \"YEAR\" => Value::ChronoDate(\n                            row.try_get::<Option<chrono::NaiveDate>, _>(c.ordinal())\n                                .expect(\"Failed to get year\")\n                                .map(Box::new),\n                        ),\n                        #[cfg(all(feature = \"with-time\", not(feature = \"with-chrono\")))]\n                        \"YEAR\" => Value::TimeDate(\n                            row.try_get::<Option<time::Date>, _>(c.ordinal())\n                                .expect(\"Failed to get year\")\n                                .map(Box::new),\n                        ),\n\n                        \"ENUM\" | \"SET\" | \"GEOMETRY\" => Value::String(\n                            row.try_get::<Option<String>, _>(c.ordinal())\n                                .expect(\"Failed to get serialized string\")\n                                .map(Box::new),\n                        ),\n\n                        #[cfg(feature = \"with-bigdecimal\")]\n                        \"DECIMAL\" => Value::BigDecimal(\n                            row.try_get::<Option<bigdecimal::BigDecimal>, _>(c.ordinal())","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/SeaQL/sea-orm/blob/e29bcd1b417c41a553b386fe94511d7c64a1c8ec/src/driver/sqlx_mysql.rs#L488-L524","documentation":"ProxyRow panicked while converting a MySQL YEAR column with `with-chrono`: the driver attempted `row.try_get::<Option<chrono::NaiveDate>, _>(c.ordinal())` and `.expect(\"Failed to get year\")` panicked because sqlx returned a decode error — the YEAR wire value (often a u16/integer) is not decodable as NaiveDate by sqlx's MySQL decoder.","triggerScenarios":"Selecting a YEAR-typed column: the MySQL wire type for YEAR is an integer year, which frequently cannot be decoded into NaiveDate, especially when the value is fetched as numeric (YEAR columns read via binary protocol return u16). Any YEAR column read through ProxyRow with chrono enabled can hit this.","commonSituations":"Schemas using YEAR(4) columns; proxy/raw-SQL paths that bypass generated entity typing; version changes in sqlx changing how YEAR is delivered; mixing proxy decoding with typed column expectations.","solutions":["Avoid decoding YEAR as a date: cast in SQL — SELECT CAST(y AS CHAR) AS y or SELECT y + 0 AS y — and read it as a String/integer.","Better: migrate the column type from YEAR to SMALLINT in the schema so it maps to an integer Value.","Select the year wrapped as a DATE ( MAKEDATE(y, 1) ) only if you genuinely need a NaiveDate.","Check the sea-orm/sqlx versions: newer sqlx versions handle YEAR differently; upgrade or downgrade in lockstep.","If only the proxy/raw path breaks, prefer generated entity queries (typed Decodable) over ProxyRow for YEAR columns."],"exampleFix":"// before — YEAR column decoded as NaiveDate, panics\nSELECT founded_year FROM companies\n\n// after — read YEAR as an integer\nSELECT founded_year + 0 AS founded_year FROM companies","handlingStrategy":"validation","validationCode":"// Check the column type before treating YEAR as a date\nlet ty: String = db.query_one(&Statement::from_string(\n    \"SELECT COLUMN_TYPE AS t FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'companies' AND COLUMN_NAME = 'founded_year'\",\n    DbBackend::MySql)).await?.unwrap().try_get(\"t\")?;\nif ty.starts_with(\"year\") { /* decode as i32/String, never NaiveDate */ }","typeGuard":"fn is_year_column(col_type: &str) -> bool {\n    col_type.eq_ignore_ascii_case(\"year\") || col_type.starts_with(\"year(\")\n}","tryCatchPattern":"// Prefer avoiding the panic entirely by mapping YEAR to integers in SQL\nlet year: Option<i32> = row.try_get(ordinal)  // via `founded_year + 0`\n    .map_err(|_| YearDecodeFallback)?;","preventionTips":["Treat MySQL YEAR as an integer, never a date, in raw/proxy queries","Migrate YEAR columns to SMALLINT in the schema","Cast YEAR to CHAR or y+0 in SELECT lists","Prefer typed entity queries over ProxyRow for YEAR columns","Verify sqlx version behavior for YEAR decoding after upgrades"],"tags":["mysql","sqlx","year","chrono","panic","decode"],"backgroundTag":"type-mismatch","analyzedSha":"e29bcd1b417c41a553b386fe94511d7c64a1c8ec","analyzedAt":"2026-09-10T11:31:52.468Z","contentChangedAt":"2026-09-10T11:31:52.468Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}