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.

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.

Appendix: 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)