SeaQL/sea-orm · error

Failed to get bytes

Error message

Failed to get bytes

What it means

This panic originates from `.expect("Failed to get bytes")` in `ProxyRow`'s MySQL driver row conversion. It means `sqlx::Row::try_get::<Option<Vec<u8>>, _>` failed for a BIT/BINARY/VARBINARY/TINYBLOB/BLOB/MEDIUMBLOB/LONGBLOB column at the given ordinal. The library panics because this conversion is treated as infallible; failure signals a real mismatch between the column's declared type and the value sqlx returned. NULLs are handled (Option), so the error is about decoding, not nullability.

Source

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

                                .expect("Failed to get small integer"),
                        ),
                        "INT" => {
                            Value::Int(row.try_get(c.ordinal()).expect("Failed to get integer"))
                        }
                        "MEDIUMINT" | "BIGINT" => Value::BigInt(
                            row.try_get(c.ordinal()).expect("Failed to get big integer"),
                        ),
                        "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")))]

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Refresh table metadata so the column's declared type string matches the live schema (`SHOW CREATE TABLE`).
  2. Confirm the column is a binary type; if it was changed to TEXT/JSON, ensure the driver maps it under the string branch instead.
  3. Check sqlx MySQL driver version — BIT decoding behavior varies; align versions.
  4. Patch the driver to propagate a DbErr rather than panicking, so failures are diagnosable at runtime.

Example fix

// before
"BIT" | "BINARY" | "VARBINARY" | ... | "LONGBLOB" => Value::Bytes(
    row.try_get::<Option<Vec<u8>>, _>(c.ordinal())
        .expect("Failed to get bytes")
        .map(Box::new),
)
// after
... => Value::Bytes(
    row.try_get::<Option<Vec<u8>>, _>(c.ordinal())
        .map_err(|e| DbErr::TryGetErr(...))? // propagate instead of panicking
        .map(Box::new),
)
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the column is a binary type before reading it as Bytes
let col = table_columns.iter().find(|c| c.name == "my_col").expect("column missing");
const BINARY_TYPES: &[&str] = &["BIT", "BINARY", "VARBINARY", "TINYBLOB", "BLOB", "MEDIUMBLOB", "LONGBLOB"];
assert!(BINARY_TYPES.contains(&col.type_name.as_str()), "expected binary column");

Try / catch

// Driver panics on decode failure; contain it at the call boundary:
std::panic::catch_unwind(|| proxy_row_from(&row, &columns))
    .map_err(|_| DbErr::Custom("binary column decode failed".into()))?

Prevention

When it happens

Trigger: Reading a MySQL binary-type column (BIT, BINARY, VARBINARY, or any BLOB) whose value cannot be decoded as `Option<Vec<u8>>` — e.g. metadata captured before a column type change, or BIT columns with widths sqlx returns as different types.

Common situations: Schema drift after altering a BLOB column to TEXT or JSON; BIT(1) columns treated as boolean by other tools; driver version differences in how MySQL BIT values are returned.

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