SeaQL/sea-orm · error

Failed to get bytes

Error message

Failed to get bytes

What it means

This panic comes from `.expect("Failed to get bytes")` in `ProxyRow`, where a Postgres BYTEA column is decoded via `row.try_get::<Option<Vec<u8>>>`. It fires when sqlx cannot decode the value as binary -- typically the runtime column type OID is not `bytea` (e.g. the column is actually TEXT/VARCHAR holding encoded data, or was altered to another type). Since the code uses `expect`, the driver's decode error becomes a panic that kills the query.

Source

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

                                .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"),
                        ),
                        #[cfg(feature = "postgres-array")]
                        "BYTEA[]" => Value::Array(
                            sea_query::ArrayType::Bytes,
                            row.try_get::<Option<Vec<Vec<u8>>>, _>(c.ordinal())
                                .expect("Failed to get bytes array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::Bytes(Some(val)))
                                            .collect(),
                                    )
                                }),
                        ),

                        #[cfg(feature = "with-bigdecimal")]
                        "NUMERIC" => Value::BigDecimal(
                            row.try_get::<Option<bigdecimal::BigDecimal>, _>(c.ordinal())

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Confirm the actual column type (`\d table`); if it is TEXT storing base64/hex, either change the entity field to String and decode in application code, or ALTER the column back to BYTEA.
  2. Cast in the query when the column is genuinely binary under another name: `SELECT decode(col, 'base64')::BYTEA AS col`.
  3. Update the entity mapping so the Rust type matches the column (String for text, Vec<u8> for bytea).
  4. Align sea-orm and sqlx versions if a dependency upgrade introduced the failure.

Example fix

// before: entity expects bytea but the column is TEXT holding base64
pub blob: Vec<u8>,

// after: read as String and decode where needed
pub blob: String, // then base64::decode(&blob) in application code
Defensive patterns

Strategy: validation

Validate before calling

let row: (String,) = sqlx::query_as(
    "SELECT data_type FROM information_schema.columns WHERE table_name = $1 AND column_name = $2"
).bind("my_table").bind("blob").fetch_one(&db).await?;
assert_eq!(row.0, "bytea", "blob must be BYTEA, got {}", row.0);

Type guard

fn as_bytes(v: &sea_orm::Value) -> Option<Vec<u8>> {
    match v {
        sea_orm::Value::Bytes(b) => b.clone(),
        _ => None,
    }
}

Prevention

When it happens

Trigger: Any SeaORM query returning a column matched as BYTEA that cannot be decoded as Option<Vec<u8>>: the column's real type is text/varchar (common when data was migrated from another DB), or the column was ALTERed away from bytea while the model still maps it to bytes.

Common situations: Migrating from MySQL blob columns into TEXT while the entity still expects Vec<u8>. `ALTER COLUMN ... TYPE TEXT` to store hex/base64 strings. Reading through views that cast bytea to text. sqlx/sea-orm version skew changing type mapping.

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