SeaQL/sea-orm · error
Failed to get timestamp
Error message
Failed to get timestamp
What it means
This panic is raised by ProxyRow when converting a MySQL TIMESTAMP column: `row.try_get::<Option<chrono::DateTime<Utc>>, _>(c.ordinal())` returned Err and `.expect("Failed to get timestamp")` panicked. sqlx cannot decode the raw wire value into the expected chrono type, usually because the actual value does not conform to the declared TIMESTAMP type. The library deliberately panics via expect instead of returning a Result, so a single bad column value aborts the whole query.
Source
Thrown at src/driver/sqlx_mysql.rs:454
"BIT" | "BINARY" | "VARBINARY" | "TINYBLOB" | "BLOB" | "MEDIUMBLOB"
| "LONGBLOB" => Value::Bytes(
row.try_get::<Option<Vec<u8>>, _>(c.ordinal())
.expect("Failed to get bytes")
.map(Box::new),
),
"CHAR" | "VARCHAR" | "TINYTEXT" | "TEXT" | "MEDIUMTEXT" | "LONGTEXT" => {
Value::String(
row.try_get::<Option<String>, _>(c.ordinal())
.expect("Failed to get string")
.map(Box::new),
)
}
#[cfg(feature = "with-chrono")]
"TIMESTAMP" => Value::ChronoDateTimeUtc(
row.try_get::<Option<chrono::DateTime<chrono::Utc>>, _>(c.ordinal())
.expect("Failed to get timestamp")
.map(Box::new),
),
#[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
"TIMESTAMP" => Value::TimeDateTime(
row.try_get::<Option<time::PrimitiveDateTime>, _>(c.ordinal())
.expect("Failed to get timestamp")
.map(Box::new),
),
#[cfg(feature = "with-chrono")]
"DATE" => Value::ChronoDate(
row.try_get::<Option<chrono::NaiveDate>, _>(c.ordinal())
.expect("Failed to get date")
.map(Box::new),
),
#[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
"DATE" => Value::TimeDate(
row.try_get::<Option<time::Date>, _>(c.ordinal())View on GitHub (pinned to e29bcd1b41)
Solutions
- Sanitize the table: find and fix/NULL out zero or invalid timestamps (SELECT ... WHERE ts = '0000-00-00 00:00:00'; UPDATE ... SET ts = NULL), and enable STRICT_ALL_TABLES/STRICT_TRANS_TABLES so MySQL rejects invalid values on insert.
- Cast non-conforming expressions back to the expected type in SQL, e.g. SELECT CAST(expr AS DATETIME) AS ts, so sqlx receives a decodable value.
- Verify column type metadata matches the value: check the declared type in information_schema.columns versus what the query actually returns for that ordinal.
- If the value arrives as a string from an older/replica server, normalize the server version or connection settings rather than the query.
- As a last resort, select the column as CHAR/VARCHAR and parse manually instead of letting the driver decode it as TIMESTAMP.
Example fix
// before — query returns zero-date and panics
let rows = db.query_all(Statement::from_string(
"SELECT created_at FROM orders", DbBackend::MySql,
)).await?;
// after — sanitize in SQL so the driver never sees an invalid timestamp
let rows = db.query_all(Statement::from_string(
"SELECT NULLIF(created_at, '0000-00-00 00:00:00') AS created_at FROM orders",
DbBackend::MySql,
)).await?; Defensive patterns
Strategy: validation
Validate before calling
// Detect undecodable TIMESTAMP values before fetching
let bad: u64 = db.query_one(&Statement::from_string(
"SELECT COUNT(*) AS n FROM orders WHERE created_at = '0000-00-00 00:00:00' OR created_at IS NOT NULL AND created_at NOT BETWEEN '1000-01-01' AND '9999-12-31'",
DbBackend::MySql)).await?.unwrap().try_get("n")?;
if bad > 0 { return Err(anyhow!("{} rows contain invalid TIMESTAMP values", bad)); } Type guard
fn valid_mysql_ts(s: &str) -> bool {
chrono::DateTime::<chrono::Utc>::from_str(s).is_ok() && s != "0000-00-00 00:00:00"
} Try / catch
// ProxyRow panics, so it cannot be caught with ?; fence it if value provenance is uncertain
let value = std::panic::catch_unwind(|| proxy_row.decode_timestamp(ordinal)).ok();
match value {
Some(v) => v,
None => fallback_load_as_string_and_parse(),
} Prevention
- Always run MySQL in strict mode (STRICT_TRANS_TABLES) so zero/invalid dates cannot be stored
- NULLIF suspicious TIMESTAMP expressions in raw SQL instead of trusting the wire type
- Cast computed columns with CAST(... AS DATETIME) to keep runtime and declared types identical
- Add a data-quality check for zero dates when inheriting legacy databases
- Upgrade sea-orm and sqlx together, never one alone
When it happens
Trigger: Executing a raw query or proxy-based query through the MySQL driver where a TIMESTAMP column contains a value sqlx cannot decode as Option<chrono::DateTime<Utc>> — e.g. the invalid MySQL zero timestamp '0000-00-00 00:00:00', a string-form timestamp returned by an expression (NOW(), UNIX_TIMESTAMP formatting), or schema metadata mismatch (column type says TIMESTAMP but the expression yields something else).
Common situations: Tables created without strict mode so '0000-00-00 00:00:00' rows exist; selecting computed/aliased expressions whose runtime type differs from the declared column; connecting to a server with a different sql_compatibility/timezone setup; upgrading sqlx versions which tightened decode rules.
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
- Failed to get timestamp
- Failed to get datetime
- Failed to get decimal
- Failed to get json
- Failed to get date
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/182d29d07a8f8c30.
Report an issue: GitHub.