SeaQL/sea-orm · error

Failed to get boolean

Error message

Failed to get boolean

What it means

This is not a returned error but a panic: while converting a sqlx Postgres row into a sea-orm `ProxyRow`, the driver matched a column whose type name is "BOOL" and called `row.try_get::<bool>(ordinal).expect("Failed to get boolean")`. `try_get` fails when the runtime value cannot be decoded as `bool` (most commonly because the value is NULL, or the underlying column type differs from the reported type name). The library uses `.expect` because it trusts the type-info match, so any mismatch aborts the thread.

Source

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

    }
}

#[cfg(feature = "proxy")]
pub(crate) fn from_sqlx_postgres_row_to_proxy_row(row: &sqlx::postgres::PgRow) -> crate::ProxyRow {
    // https://docs.rs/sqlx-postgres/0.7.2/src/sqlx_postgres/type_info.rs.html
    // https://docs.rs/sqlx-postgres/0.7.2/sqlx_postgres/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() {
                        "BOOL" => {
                            Value::Bool(row.try_get(c.ordinal()).expect("Failed to get boolean"))
                        }
                        #[cfg(feature = "postgres-array")]
                        "BOOL[]" => Value::Array(
                            sea_query::ArrayType::Bool,
                            row.try_get::<Option<Vec<bool>>, _>(c.ordinal())
                                .expect("Failed to get boolean array")
                                .map(|vals| {
                                    Box::new(
                                        vals.into_iter()
                                            .map(|val| Value::Bool(Some(val)))
                                            .collect(),
                                    )
                                }),
                        ),

                        "\"CHAR\"" => Value::TinyInt(
                            row.try_get(c.ordinal())
                                .expect("Failed to get small integer"),

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Read the column as `Option<bool>` (change to `row.try_get::<Option<bool>, _>(c.ordinal())` and map to `Value::Bool(opt)` or `Value::TinyInt(None)`) so NULL no longer panics.
  2. Make the column NOT NULL (or add a DEFAULT) with `ALTER TABLE t ALTER COLUMN col SET NOT NULL;` so a scalar `bool` decode is always valid.
  3. COALESCE the column in the query (`COALESCE(col, false)`) if NULL should be treated as false.
  4. Check `search_path`/schema for a user-defined type named BOOL shadowing the builtin; qualify or rename it.
  5. If the mismatch comes from a DOMAIN type, decode via the base type or cast in SQL (`col::boolean`).

Example fix

// before (panics on NULL)
"BOOL" => Value::Bool(row.try_get(c.ordinal()).expect("Failed to get boolean")),
// after (NULL-safe)
"BOOL" => Value::Bool(
    row.try_get::<Option<bool>, _>(c.ordinal())
        .expect("Failed to get boolean")
        .unwrap_or_default(),
),
Defensive patterns

Strategy: try-catch

Validate before calling

// inspect column types/typmods before running the query
let types: Vec<String> = cols.iter().map(|c| format!("{}:{}", c.name(), c.type_info().name())).collect();
// and check nullability in the catalog:
// SELECT column_name, is_nullable FROM information_schema.columns
//   WHERE table_name = 't' AND data_type IN ('boolean');

Type guard

fn as_bool(row: &ProxyRow, col: &str) -> Option<bool> {
    match row.value(col) {
        Some(Value::Bool(v)) => v,
        _ => None,
    }
}

Try / catch

// the library panics (expect), so guard at the query boundary
let result = std::panic::catch_unwind(|| proxy_row_get_bool(&row, "is_active"));
match result {
    Ok(v) => v,
    Err(_) => treat_as_null_or_default(), // fall back / log column metadata
}

Prevention

When it happens

Trigger: Fetching a row via the sync Postgres driver where a column reports `type_info().name() == "BOOL"` but `row.try_get::<bool, _>(ordinal)` returns Err — i.e. the value is NULL (sqlx `UnexpectedNullError`) or the physical column is a compatible-but-different type (e.g. a domain over bool, or a custom type shadowing BOOL in a schema earlier in `search_path`).

Common situations: Querying a nullable boolean column directly through ProxyRow instead of through an entity model that wraps it in `Option<bool>`; using a Postgres DOMAIN type over boolean that reports as the domain name; a schema/search_path change making `BOOL` resolve to a user-defined type; reading a `bool` column whose value is NULL because of a LEFT JOIN miss.

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