SeaQL/sea-orm · error

Failed to get timetz

Error message

Failed to get timetz

What it means

Under `with-chrono`, a `TIMETZ` (time with time zone) column is decoded by ProxyRow into `chrono::NaiveTime` via `try_get::<Option<chrono::NaiveTime>>`; on a decode Err, `.expect("Failed to get timetz")` panics. Note TIMETZ carries an offset that NaiveTime drops, so the mapping is inherently lossy and requires sqlx's timetz->NaiveTime decode path.

Source

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

                            feature = "postgres-array"
                        ))]
                        "TIMESTAMPTZ[]" => Value::Array(
                            sea_query::ArrayType::TimeDateTimeWithTimeZone,
                            row.try_get::<Option<Vec<time::OffsetDateTime>>, _>(c.ordinal())
                                .expect("Failed to get timestamptz array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::TimeDateTimeWithTimeZone(Some(val)))
                                            .collect(),
                                    )
                                }),
                        ),

                        #[cfg(feature = "with-chrono")]
                        "TIMETZ" => Value::ChronoTime(
                            row.try_get::<Option<chrono::NaiveTime>, _>(c.ordinal())
                                .expect("Failed to get timetz"),
                        ),
                        #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
                        "TIMETZ" => {
                            Value::TimeTime(row.try_get(c.ordinal()).expect("Failed to get timetz"))
                        }

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

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Prefer migrating the column to plain `time` (offsets in TIMETZ are legacy) so it maps cleanly to NaiveTime: `ALTER TABLE t ALTER COLUMN c TYPE time USING c AT TIME ZONE 'UTC';`
  2. Verify the column udt_name is `timetz` and sqlx has its `chrono` feature enabled with a compatible version.
  3. If the column is not timetz, fix the schema or adjust the query to cast (`c::timetz`).
  4. Work around by selecting as text and parsing offset-aware with chrono yourself.

Example fix

// before: legacy column
// shift_start time with time zone

// after
// ALTER TABLE shifts ALTER COLUMN shift_start TYPE time USING shift_start AT TIME ZONE 'UTC';
Defensive patterns

Strategy: validation

Validate before calling

let ty: (String,) = sqlx::query_as(
    "SELECT udt_name FROM information_schema.columns WHERE table_name = $1 AND column_name = $2",
).bind("shifts").bind("shift_start").fetch_one(db).await?;
if ty.0 != "timetz" { return Err(anyhow!("shift_start is {}, expected timetz", ty.0)); }

Type guard

fn is_timetz(udt_name: &str) -> bool { udt_name == "timetz" }

Try / catch

let t = row.try_get::<Option<chrono::NaiveTime>, _>(idx)
    .map_err(|e| DecodeError::Timetz(e.to_string()))?;

Prevention

When it happens

Trigger: Selecting a TIMETZ column when sqlx cannot decode it into NaiveTime: column is actually `time`/`timestamp`/text, a custom domain over timetz, or sqlx's chrono decoder for the timetz OID is unavailable at the compiled version.

Common situations: Tables using `time with time zone` (widely discouraged in Postgres); schema migration changing column type; sqlx/sea-orm version skew removing or gating the decoder.

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