SeaQL/sea-orm · error

Failed to get string

Error message

Failed to get string

What it means

This panic comes from `.expect("Failed to get string")` in `ProxyRow`'s MySQL driver conversion. `sqlx::Row::try_get::<Option<String>, _>` failed for a CHAR/VARCHAR/TINYTEXT/TEXT/MEDIUMTEXT/LONGTEXT column at `c.ordinal()`. Because the code uses `expect`, the decode failure panics instead of returning an error. It usually means the column is not actually a text type or the value cannot be decoded as UTF-8-compatible String.

Source

Thrown at sea-orm-sync/src/driver/sqlx_mysql.rs:438

                        ),
                        "FLOAT" => {
                            Value::Float(row.try_get(c.ordinal()).expect("Failed to get float"))
                        }
                        "DOUBLE" => {
                            Value::Double(row.try_get(c.ordinal()).expect("Failed to get double"))
                        }

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

                        "CHAR" | "VARCHAR" | "TINYTEXT" | "TEXT" | "MEDIUMTEXT" | "LONGTEXT" => {
                            Value::String(
                                row.try_get::<Option<String>, _>(c.ordinal())
                                    .expect("Failed to get string")
                                    .map(Box::new),
                            )
                        }

                        #[cfg(feature = "with-chrono")]
                        "TIMESTAMP" => Value::ChronoDateTimeUtc(
                            row.try_get::<Option<chrono::DateTime<chrono::Utc>>, _>(c.ordinal())
                                .expect("Failed to get timestamp")
                                .map(Box::new),
                        ),
                        #[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")
                                .map(Box::new),
                        ),

                        #[cfg(feature = "with-chrono")]

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Refresh the table metadata so the text-type mapping matches the live schema.
  2. Verify the column is a character type and uses a text collation; convert binary columns before reading them as strings.
  3. Ensure consistent charset configuration (utf8mb4) across server, connection, and sqlx version.
  4. Change the driver to return DbErr instead of `expect` so the underlying sqlx decode error is visible.

Example fix

// before
"CHAR" | "VARCHAR" | ... | "LONGTEXT" => Value::String(
    row.try_get::<Option<String>, _>(c.ordinal())
        .expect("Failed to get string")
        .map(Box::new),
)
// after
... => Value::String(
    row.try_get::<Option<String>, _>(c.ordinal())
        .map_err(|e| DbErr::TryGetErr(...))? // propagate instead of panicking
        .map(Box::new),
)
Defensive patterns

Strategy: validation

Validate before calling

// Verify the column is a text type with a text collation before reading as String
let col = table_columns.iter().find(|c| c.name == "my_col").expect("column missing");
const TEXT_TYPES: &[&str] = &["CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT"];
assert!(TEXT_TYPES.contains(&col.type_name.as_str()), "expected text column, got {}", col.type_name);

Try / catch

// The panic originates in the driver; wrap the boundary:
std::panic::catch_unwind(|| proxy_row_from(&row, &columns))
    .map_err(|_| DbErr::Custom("text column decode failed".into()))?

Prevention

When it happens

Trigger: Reading a MySQL text-type column whose value fails String decoding — commonly after the column was altered to BLOB/BINARY or JSON while cached metadata still says CHAR/VARCHAR/TEXT, or invalid character encodings sqlx cannot map to String.

Common situations: Metadata captured before an ALTER TABLE; columns created with binary collations; MySQL server/connector charset mismatches (e.g. latin1 vs utf8mb4) causing decode failures.

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/701c55954eed2a2d. Report an issue: GitHub.