SeaQL/sea-orm · error

Failed to get timestamp array

Error message

Failed to get timestamp array

What it means

This is a panic (not a catchable error) raised by `.expect()` inside SeaORM's ProxyRow conversion for Postgres. When a column is reported as `TIMESTAMP[]`, the driver calls sqlx `try_get::<Option<Vec<chrono::NaiveDateTime>>>` on it; if sqlx cannot decode the column into that exact Rust type (type OID mismatch, NULL handling difference, or feature/crate version skew), it returns an Err and this expect panics with "Failed to get timestamp array". It almost always means the actual Postgres column type does not match what the string-matched branch assumed.

Source

Thrown at src/driver/sqlx_postgres.rs:729

                                }),
                        ),

                        #[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(),
                                    )
                                }),
                        ),
                        #[cfg(all(
                            feature = "with-time",
                            not(feature = "with-chrono"),
                            feature = "postgres-array"
                        ))]
                        "TIMESTAMP[]" => Value::Array(
                            sea_query::ArrayType::TimeDateTime,
                            row.try_get::<Option<Vec<time::PrimitiveDateTime>>, _>(c.ordinal())
                                .expect("Failed to get timestamp array")
                                .map(|vals| {

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Verify the actual Postgres column type with `\d table` and ensure it is exactly `timestamp[]` (not `timestamptz[]`); align the column or use the matching Value variant branch.
  2. Pin compatible sea-orm / sea-orm-serde / sqlx versions in Cargo.lock so sqlx's chrono array decodes match what SeaORM expects.
  3. Ensure the `with-chrono` and `postgres-array` features of sea-orm are enabled together so the correct decode branch is compiled in.
  4. Avoid `.expect` by casting in SQL (`SELECT col::text[]`) or selecting the column as string when its type is uncertain.

Example fix

// before: schema has TIMESTAMPTZ[] but code assumes TIMESTAMP[]
let rows: Vec<ProxyRow> = query.map(|row| row.into_proxy_row()).await?; // panics

// after: normalize the column type in SQL
let rows = Statement::from_string(
    db.get_database_backend(),
    "SELECT created_ats::timestamp[] AS created_ats FROM events",
);
Defensive patterns

Strategy: try-catch

Validate before calling

// Before running the query, confirm the column type
let row: Option<String> = sqlx::query_scalar(
    "SELECT data_type || '[]' FROM information_schema.columns WHERE table_name=$1 AND column_name=$2")
    .bind("events").bind("created_ats").fetch_optional(db).await?;
assert_eq!(row.as_deref(), Some("timestamp[]"));

Type guard

fn is_timestamp_array(t: &str) -> bool { t.eq_ignore_ascii_case("timestamp[]") }

Try / catch

// `.expect` panics and is not catchable safely; pre-validate the column type or
catch upstream via catch_unwind if unavoidable:
let result = std::panic::catch_unwind(|| build_proxy_rows(stmt));
match result { Ok(rows) => rows, Err(_) => fallback_to_manual_decode() }

Prevention

When it happens

Trigger: Selecting a `TIMESTAMP[]` (timestamp without time zone array) column through the proxy row path while the `with-chrono` + `postgres-array` features are enabled, and sqlx refuses to decode the value into `Vec<chrono::NaiveDateTime>` — e.g. the column is actually `TIMESTAMPTZ[]`, the driver's type string matched wrongly, or a sqlx/chrono version mismatch changes decode support.

Common situations: Schema drift (column changed from TIMESTAMP[] to TIMESTAMPTZ[] or a domain over it), using `text[]`-typed placeholder results, mismatched sea-orm/sqlx minor versions where the chrono `NaiveDateTime` impl is feature-gated differently, or raw queries feeding ProxyRow whose declared types were derived from a different database backend.

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