SeaQL/sea-orm · error

Failed to get serialized string

Error message

Failed to get serialized string

What it means

This panic comes from an `.expect("Failed to get serialized string")` inside sea-orm's sqlx MySQL driver while converting a sqlx row into a ProxyRow. For columns whose MySQL type is ENUM, SET, or GEOMETRY, the driver decodes the raw value as an Option<String>; if sqlx returns a decode error (type mismatch, NULL handling, or a value that cannot be represented as a string), the expect panics. SeaORM uses expect() here because the column type was already inspected via type_info, so a failure indicates an unexpected driver/type state rather than a normal error path.

Source

Thrown at src/driver/sqlx_mysql.rs:518

                                .map(Box::new),
                        ),

                        #[cfg(feature = "with-chrono")]
                        "YEAR" => Value::ChronoDate(
                            row.try_get::<Option<chrono::NaiveDate>, _>(c.ordinal())
                                .expect("Failed to get year")
                                .map(Box::new),
                        ),
                        #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
                        "YEAR" => Value::TimeDate(
                            row.try_get::<Option<time::Date>, _>(c.ordinal())
                                .expect("Failed to get year")
                                .map(Box::new),
                        ),

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

                        #[cfg(feature = "with-bigdecimal")]
                        "DECIMAL" => Value::BigDecimal(
                            row.try_get::<Option<bigdecimal::BigDecimal>, _>(c.ordinal())
                                .expect("Failed to get decimal")
                                .map(Box::new),
                        ),
                        #[cfg(all(
                            feature = "with-rust_decimal",
                            not(feature = "with-bigdecimal")
                        ))]
                        "DECIMAL" => Value::Decimal(
                            row.try_get::<Option<rust_decimal::Decimal>, _>(c.ordinal())
                                .expect("Failed to get decimal")
                                .map(Box::new),
                        ),

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Avoid selecting ENUM/SET/GEOMETRY columns directly; cast them to plain VARCHAR in SQL, e.g. `CAST(geom AS CHAR)` or `COLUMN::as_text()`.
  2. Ensure the sqlx `mysql` feature with the needed `runtime`/`tls` flags matches the crate versions sea-orm was built against; pin compatible versions.
  3. For GEOMETRY, retrieve ST_AsText(geom) / ST_AsBinary(geom) in the query instead of the raw column.
  4. If upgrading sqlx or sea-orm, check the changelog for MySQL ENUM/SET decode changes and adjust column types or entity definitions.
  5. As a workaround, wrap the query so the offending column is returned as a JSON or TEXT alias.

Example fix

// before
let rows = MyEntity::find().from_raw_sql(Statement::from_string(
    DatabaseBackend::MySql, "SELECT geom FROM places",
)).into_model::<MyModel>().all(db).await?;

// after
let rows = MyEntity::find().from_raw_sql(Statement::from_string(
    DatabaseBackend::MySql, "SELECT ST_AsText(geom) AS geom FROM places",
)).into_model::<MyModel>().all(db).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Before querying, verify column types are decode-safe:
let check = db.query_all(Statement::from_string(
    DatabaseBackend::MySql,
    "SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS
     WHERE TABLE_NAME = 'places' AND DATA_TYPE IN ('enum','set','geometry')",
)).await?;
if !check.is_empty() {
    // cast these columns in your SELECT (ST_AsText / CAST(... AS CHAR))
}

Prevention

When it happens

Trigger: Fetching a row from MySQL whose column type_info().name() is "ENUM", "SET", or "GEOMETRY" and where `row.try_get::<Option<String>, _>(c.ordinal())` fails -- e.g. the driver returns a non-string representation for GEOMETRY binary data, or the sqlx type decoding for that column fails.

Common situations: Selecting GEOMETRY/POINT/POLYGON columns directly (they are decoded as strings here but binary representations can fail), custom ENUM definitions on MySQL with unusual collations, sqlx version upgrades that changed how ENUM/SET values are decoded, and raw SQL queries through sea-orm's proxy/driver layer that return such columns.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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