SeaQL/sea-orm · error

Failed to get boolean

Error message

Failed to get boolean

What it means

During proxy-row conversion (feature "proxy"), each SQLite column's declared type_info is matched and the value is decoded with sqlx Row::try_get. For a "BOOLEAN" column the library calls row.try_get::<bool>(ordinal) and unwraps it with expect("Failed to get boolean"). This panics when the underlying SQLite value is NULL or cannot be decoded as a bool, because SQLite's dynamic typing can store values that do not match the declared affinity.

Source

Thrown at src/driver/sqlx_sqlite.rs:424

    }
}

#[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. Ensure BOOLEAN columns are NOT NULL or provide a default so NULL never reaches the row
  2. Coalesce NULLs in the query: SELECT IFNULL(active, 0) AS active ...
  3. Avoid the proxy feature or use a non-proxy driver so decoding returns DbErr instead of panicking
  4. Cast the value in SQL to an integer and decode defensively

Example fix

// before
SELECT active FROM "user";
// after
SELECT IFNULL(active, 0) AS active FROM "user";
Defensive patterns

Strategy: try-catch

Validate before calling

// Before reading, coalesce NULLs and validate affinity in SQL:
// SELECT IFNULL(active, 0) AS active FROM "user";
fn is_valid_bool_cell(v: Option<i64>) -> bool { v.is_some() }

Type guard

fn as_bool(v: &sea_query::Value) -> Option<bool> {
    match v { sea_query::Value::Bool(b) => Some(*b), sea_query::Value::TinyInt(i) => Some(*i != 0), _ => None }
}

Try / catch

// Proxy conversion panics (expect), so isolate it:
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| from_sqlx_sqlite_row_to_proxy_row(&row)));
match result { Ok(proxy_row) => /* ... */, Err(_) => /* fall back to non-proxy decode or DbErr::RecordNotFound-like error */ }

Prevention

When it happens

Trigger: Calling any query through the proxy driver against SQLite where a BOOLEAN-declared column contains NULL (the non-Option try_get used here cannot decode NULL) or a non-integer value, e.g. raw SQL inserting text into a boolean column.

Common situations: Raw SQL migrations inserting NULL into NOT-omitted boolean columns; schema declared BOOLEAN but data written by another tool as text; SELECT with computed expressions typed as NULL.

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