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`, where a Postgres VARCHAR/CHAR/TEXT/NAME column is decoded via `row.try_get::<Option<String>>`. It fires when sqlx cannot decode the column's value into a UTF-8 string -- most commonly because the runtime column type OID is not a text-family type (e.g. the column was changed to BYTEA, a numeric, or a custom type) or the bytes are not valid UTF-8 (e.g. a `bytea` or `char(n)` with invalid encoding). `expect` escalates the driver error to a panic.

Source

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

                            Value::Double(row.try_get(c.ordinal()).expect("Failed to get double"))
                        }
                        #[cfg(feature = "postgres-array")]
                        "FLOAT8[]" | "DOUBLE PRECISION[]" => Value::Array(
                            sea_query::ArrayType::Double,
                            row.try_get::<Option<Vec<f64>>, _>(c.ordinal())
                                .expect("Failed to get double array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::Double(Some(val)))
                                            .collect(),
                                    )
                                }),
                        ),

                        "VARCHAR" | "CHAR" | "TEXT" | "NAME" => Value::String(
                            row.try_get::<Option<String>, _>(c.ordinal())
                                .expect("Failed to get string"),
                        ),
                        #[cfg(feature = "postgres-array")]
                        "VARCHAR[]" | "CHAR[]" | "TEXT[]" | "NAME[]" => Value::Array(
                            sea_query::ArrayType::String,
                            row.try_get::<Option<Vec<String>>, _>(c.ordinal())
                                .expect("Failed to get string array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::String(Some(val)))
                                            .collect(),
                                    )
                                }),
                        ),

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

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Check the actual column type and server encoding (`\d table`, `SHOW server_encoding`); align the entity field or fix the data encoding.
  2. Cast in the query: `SELECT col::TEXT AS col` so decode receives a text value.
  3. If data is truly binary, map the field to Vec<u8> (Bytes) instead of String.
  4. Align sea-orm/sqlx versions and confirm the `sqlx-postgres` feature set is intact.

Example fix

// before: model expects String but the column holds binary data
pub payload: String,

// after: map the BYTEA column to bytes
pub payload: Vec<u8>,
Defensive patterns

Strategy: validation

Validate before calling

let rows: Vec<(String, String)> = sqlx::query_as(
    "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = $1"
).bind("my_table").fetch_all(&db).await?;
for (name, ty) in rows {
    if ["name", "title"].contains(&name.as_str()) {
        assert!(matches!(ty.as_str(), "character varying" | "character" | "text" | "name"), "{} has unexpected type {}", name, ty);
    }
}

Type guard

fn as_string(v: &sea_orm::Value) -> Option<String> {
    match v {
        sea_orm::Value::String(s) => s.clone(),
        _ => None,
    }
}

Prevention

When it happens

Trigger: Any SeaORM query whose result includes a column matched as VARCHAR/CHAR/TEXT/NAME that cannot be decoded as Option<String>: actual column type changed (e.g. to BYTEA or CITEXT-like extension types), database encoding is not UTF-8-compatible for the value, or a view returns a non-text type under a text-named column.

Common situations: `ALTER COLUMN ... TYPE BYTEA` or type changed for storage reasons while the model still says String. Non-UTF8 server encoding (e.g. SQL_ASCII/Latin1) with binary data in text columns. Reading via views or FDWs with remapped types. sqlx/sea-orm version skew.

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