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
- 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';`
- Verify the column udt_name is `timetz` and sqlx has its `chrono` feature enabled with a compatible version.
- If the column is not timetz, fix the schema or adjust the query to cast (`c::timetz`).
- 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
- Avoid `time with time zone` columns entirely; Postgres itself discourages them
- Migrate timetz -> time (offsets via AT TIME ZONE 'UTC') so chrono NaiveTime decodes directly
- Enable `with-chrono` on sea-orm-sync and `chrono` on sqlx together
- Verify column types after migrations with an information_schema assertion
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
- Failed to get time array
- Failed to get timestamptz
- Failed to get timestamptz array
- Failed to get timetz array
- Failed to get timetz
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/22f9d9d2cafa4bce.
Report an issue: GitHub.