SeaQL/sea-orm · error

Failed to get boolean

Error message

Failed to get boolean

What it means

Panic in sea-orm-sync's SQLite driver when a column whose type_info name is "BOOLEAN" cannot be decoded into the expected boolean type while constructing a ProxyRow. SQLite stores booleans as integers, so this fires when sqlx reports BOOLEAN but the underlying value is not a valid 0/1 integer (or is NULL where a non-Option bool is expected).

Source

Thrown at sea-orm-sync/src/driver/sqlx_sqlite.rs:415

    }
}

#[cfg(feature = "proxy")]
pub(crate) fn from_sqlx_sqlite_row_to_proxy_row(row: &sqlx::sqlite::SqliteRow) -> crate::ProxyRow {
    // https://docs.rs/sqlx-sqlite/0.7.2/src/sqlx_sqlite/type_info.rs.html
    // https://docs.rs/sqlx-sqlite/0.7.2/sqlx_sqlite/types/index.html
    use sea_query::Value;
    use sqlx::{Column, Row, TypeInfo};
    crate::ProxyRow {
        values: row
            .columns()
            .iter()
            .map(|c| {
                (
                    c.name().to_string(),
                    match c.type_info().name() {
                        "BOOLEAN" => {
                            Value::Bool(row.try_get(c.ordinal()).expect("Failed to get boolean"))
                        }

                        "INTEGER" => {
                            Value::Int(row.try_get(c.ordinal()).expect("Failed to get integer"))
                        }

                        "BIGINT" | "INT8" => Value::BigInt(
                            row.try_get(c.ordinal()).expect("Failed to get big integer"),
                        ),

                        "REAL" => {
                            Value::Double(row.try_get(c.ordinal()).expect("Failed to get double"))
                        }

                        "TEXT" => Value::String(
                            row.try_get::<Option<String>, _>(c.ordinal())
                                .expect("Failed to get string")
                                .map(Box::new),

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Sanitize stored values so booleans are exactly 0 or 1 integers (UPDATE col SET col = CASE ... )
  2. Make the column NOT NULL with a DEFAULT 0 to eliminate NULL decodes
  3. Check with SELECT typeof(col), col to find offending values before re-querying via ProxyRow
  4. Replace .expect with error propagation and fall back to Value::Int for non-boolean values

Example fix

// before
"BOOLEAN" => {
    Value::Bool(row.try_get(c.ordinal()).expect("Failed to get boolean"))
}
// after
"BOOLEAN" => {
    Value::Bool(row.try_get::<Option<bool>, _>(c.ordinal())
        .expect("Failed to get boolean")
        .unwrap_or(false))
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure SQLite boolean columns hold only 0/1 integers:
// SELECT typeof(col), col FROM t WHERE col NOT IN (0, 1) OR col IS NULL;

Type guard

fn is_valid_bool_storage(v: Option<i64>) -> bool { matches!(v, Some(0) | Some(1)) }

Try / catch

let row = std::panic::catch_unwind(|| proxy_query(db)).unwrap_or_else(|_| fallback_row());

Prevention

When it happens

Trigger: Reading a SQLite BOOLEAN-declared column whose stored value is NULL (try_get into non-Option bool), or whose stored value is something other than 0/1 (e.g. text 'true' or integer 2).

Common situations: Booleans inserted by another tool as strings 'true'/'false'; columns declared BOOLEAN but populated with arbitrary integers; NULL values in a NOT-NULL-assumed boolean column during migration from other databases.

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