SeaQL/sea-orm · error

Failed to get timestamp

Error message

Failed to get timestamp

What it means

This panic occurs in the PostgreSQL row-decoding path of sea-orm-sync's sqlx driver when a TIMESTAMP column cannot be decoded into chrono::NaiveDateTime. The driver matches on the PostgreSQL type name ("TIMESTAMP") and calls row.try_get::<Option<chrono::NaiveDateTime>>; sqlx returns a type-mismatch or decode error when the actual wire value is not compatible with the requested Rust type, and the .expect turns that into a panic. It almost always means the column's actual Postgres type differs from what the match arm assumed (e.g. TIMESTAMPTZ vs TIMESTAMP) or a required feature crate version mismatch.

Source

Thrown at sea-orm-sync/src/driver/sqlx_postgres.rs:704

                        ),
                        #[cfg(all(feature = "with-mac_address", feature = "postgres-array"))]
                        "MACADDR[]" | "MACADDR8[]" => Value::Array(
                            sea_query::ArrayType::MacAddress,
                            row.try_get::<Option<Vec<mac_address::MacAddress>>, _>(c.ordinal())
                                .expect("Failed to get mac address array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::MacAddress(Some(val)))
                                            .collect(),
                                    )
                                }),
                        ),

                        #[cfg(feature = "with-chrono")]
                        "TIMESTAMP" => Value::ChronoDateTime(
                            row.try_get::<Option<chrono::NaiveDateTime>, _>(c.ordinal())
                                .expect("Failed to get timestamp"),
                        ),
                        #[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"),
                        ),

                        #[cfg(all(feature = "with-chrono", feature = "postgres-array"))]
                        "TIMESTAMP[]" => Value::Array(
                            sea_query::ArrayType::ChronoDateTime,
                            row.try_get::<Option<Vec<chrono::NaiveDateTime>>, _>(c.ordinal())
                                .expect("Failed to get timestamp array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::ChronoDateTime(Some(val)))
                                            .collect(),
                                    )

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Check the actual column type in Postgres (\d table or information_schema.columns) and ensure it is TIMESTAMP (without time zone); migrate to `ALTER COLUMN ... TYPE timestamp` if it is TIMESTAMPTZ.
  2. Align sqlx and chrono versions/features so sqlx's `chrono` decode impl is enabled and compatible with the chrono crate sea-orm-sync links.
  3. Catch the panic at a higher level by pre-validating result column types before hydrating ProxyRow, or patch the driver arm to try multiple types (TIMESTAMP/TIMESTAMPTZ).
  4. If you control the query, cast in SQL: `SELECT col::timestamp FROM ...` to force a decodable type.

Example fix

// before
SELECT updated_at FROM events; -- updated_at is TIMESTAMPTZ -> panic "Failed to get timestamp"
// after
SELECT updated_at::timestamp AS updated_at FROM events;
Defensive patterns

Strategy: validation

Validate before calling

-- run before hydration
SELECT column_name, data_type FROM information_schema.columns
WHERE table_name = 'your_table' AND data_type NOT IN ('timestamp without time zone');
-- empty result = safe to decode TIMESTAMP columns as NaiveDateTime

Type guard

fn is_plain_timestamp(col: &PgTypeInfo) -> bool { col.name().eq_ignore_ascii_case("timestamp") }

Try / catch

let ts = row.try_get::<Option<chrono::NaiveDateTime>, _>(idx)
    .map_err(|e| DecodeError::Timestamp { column: idx, source: e })?;

Prevention

When it happens

Trigger: Reading a row where column c's Postgres type name is "TIMESTAMP" but the underlying value cannot be decoded as Option<chrono::NaiveDateTime>: e.g. the column is actually TIMESTAMPTZ, the driver matched a stale/aliased type string, or the with-chrono sqlx feature decoders conflict with the installed chrono version.

Common situations: Queries hitting columns defined as TIMESTAMPTZ (which some servers/drivers report differently), schema drift after a migration changed the column type, custom domain types over timestamp, or a chrono/sqlx version mismatch where sqlx's chrono impl is compiled for a different feature set.

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