SeaQL/sea-orm · error

Failed to get timestamp

Error message

Failed to get timestamp

What it means

Panic when sea-orm-sync's SQLite driver (with-chrono feature) cannot decode a "DATETIME" column into Option<chrono::DateTime<Utc>> while building a ProxyRow. sqlx requires specific string formats (RFC3339 with offset) for DateTime<Utc>, so any DATETIME value stored in a different format — or NULL handled incorrectly — triggers this panic.

Source

Thrown at sea-orm-sync/src/driver/sqlx_sqlite.rs:448

                        "TEXT" => Value::String(
                            row.try_get::<Option<String>, _>(c.ordinal())
                                .expect("Failed to get string")
                                .map(Box::new),
                        ),

                        "BLOB" => Value::Bytes(
                            row.try_get::<Option<Vec<u8>>, _>(c.ordinal())
                                .expect("Failed to get bytes")
                                .map(Box::new),
                        ),

                        #[cfg(feature = "with-chrono")]
                        "DATETIME" => {
                            use chrono::{DateTime, Utc};

                            Value::ChronoDateTimeUtc(
                                row.try_get::<Option<DateTime<Utc>>, _>(c.ordinal())
                                    .expect("Failed to get timestamp")
                                    .map(Box::new),
                            )
                        }
                        #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
                        "DATETIME" => {
                            use time::OffsetDateTime;
                            Value::TimeDateTimeWithTimeZone(
                                row.try_get::<Option<OffsetDateTime>, _>(c.ordinal())
                                    .expect("Failed to get timestamp")
                                    .map(Box::new),
                            )
                        }
                        #[cfg(feature = "with-chrono")]
                        "DATE" => {
                            use chrono::NaiveDate;
                            Value::ChronoDate(
                                row.try_get::<Option<NaiveDate>, _>(c.ordinal())
                                    .expect("Failed to get date")

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Normalize stored timestamps to RFC3339 with UTC offset (e.g. strftime('%Y-%m-%dT%H:%M:%SZ', col)) or re-write via datetime(col)
  2. Write timestamps through chrono-typed entity fields so sqlx serializes the expected format
  3. Check for NULL/epoch-integer values in the column and fix them before querying via ProxyRow
  4. Propagate the sqlx error with column context instead of .expect and fall back to string values

Example fix

// before
Value::ChronoDateTimeUtc(
    row.try_get::<Option<DateTime<Utc>>, _>(c.ordinal())
        .expect("Failed to get timestamp")
        .map(Box::new),
)
// after
Value::ChronoDateTimeUtc(
    row.try_get::<Option<DateTime<Utc>>, _>(c.ordinal())
        .unwrap_or_else(|e| panic!("Failed to get timestamp for col {} ({}): {}", c.name(), c.type_info().name(), e))
        .map(Box::new),
)   // root fix: ensure stored text is RFC3339, e.g. UPDATE t SET col = strftime('%Y-%m-%dT%H:%M:%SZ', col)
Defensive patterns

Strategy: validation

Validate before calling

// Verify DATETIME columns store RFC3339-parseable UTC timestamps:
// SELECT col FROM t WHERE datetime(col) IS NULL AND col IS NOT NULL;
fn parses_as_utc(s: &str) -> bool { chrono::DateTime::parse_from_rfc3339(s).is_ok() }

Type guard

fn is_rfc3339(s: &str) -> bool { chrono::DateTime::parse_from_rfc3339(s).is_ok() }

Try / catch

let row = std::panic::catch_unwind(|| proxy_query(db)).unwrap_or_else(|_| fallback_row());

Prevention

When it happens

Trigger: Reading a SQLite DATETIME column whose stored text is not parseable as DateTime<Utc> (e.g. '2024-01-02 03:04:05' without offset or 'T' separator, unix epoch integers, naive local time) under the with-chrono feature.

Common situations: Timestamps written by other tools/libraries in SQLite's default 'YYYY-MM-DD HH:MM:SS' format; epoch seconds stored as INTEGER in a DATETIME column; values written by Python/Ruby ORMs with different formats; switching between with-chrono and with-time features.

Related errors


AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10). Data as JSON: /api/errors/8e71434673a6ea55. Report an issue: GitHub.