SeaQL/sea-orm · error
Failed to get boolean
Error message
Failed to get boolean
What it means
In the sqlx MySQL ProxyRow conversion, a column typed TINYINT(1)/BOOLEAN is read with row.try_get::<bool, _>(ordinal).expect("Failed to get boolean"). If the actual runtime value is not a bool (type-info mismatch, NULL, or driver type-name drift), try_get errors and the expect panics. This is a strict type-decoding assumption inside proxy/derive-based row conversion.
Source
Thrown at src/driver/sqlx_mysql.rs:397
}
}
#[cfg(feature = "proxy")]
pub(crate) fn from_sqlx_mysql_row_to_proxy_row(row: &sqlx::mysql::MySqlRow) -> crate::ProxyRow {
// https://docs.rs/sqlx-mysql/0.7.2/src/sqlx_mysql/protocol/text/column.rs.html
// https://docs.rs/sqlx-mysql/0.7.2/sqlx_mysql/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() {
"TINYINT(1)" | "BOOLEAN" => {
Value::Bool(row.try_get(c.ordinal()).expect("Failed to get boolean"))
}
"TINYINT UNSIGNED" => Value::TinyUnsigned(
row.try_get(c.ordinal())
.expect("Failed to get unsigned tiny integer"),
),
"SMALLINT UNSIGNED" => Value::SmallUnsigned(
row.try_get(c.ordinal())
.expect("Failed to get unsigned small integer"),
),
"INT UNSIGNED" => Value::Unsigned(
row.try_get(c.ordinal())
.expect("Failed to get unsigned integer"),
),
"MEDIUMINT UNSIGNED" | "BIGINT UNSIGNED" => Value::BigUnsigned(
row.try_get(c.ordinal())
.expect("Failed to get unsigned big integer"),
),
"TINYINT" => Value::TinyInt(View on GitHub (pinned to e29bcd1b41)
Solutions
- Make the column NOT NULL or use a nullable-aware decode (Option<bool>) instead of try_get::<bool>.
- Coalesce NULLs in SQL: SELECT IFNULL(flag, 0) AS flag.
- Match the declared type-info string exactly with what your sqlx version reports for the column.
- Replace expect with a mapped DbErr (QueryAssert/TypeNotFound) instead of panicking.
Example fix
// before
"TINYINT(1)" | "BOOLEAN" => Value::Bool(row.try_get(c.ordinal()).expect("Failed to get boolean")),
// after
"TINYINT(1)" | "BOOLEAN" => Value::Bool(row.try_get::<Option<bool>, _>(c.ordinal())
.map_err(|e| DbErr::Query(RuntimeErr::Protocol(e.to_string())))?
.unwrap_or(false)), Defensive patterns
Strategy: validation
Validate before calling
-- Ensure boolean columns are NOT NULL or defaulted before decoding through the proxy: ALTER TABLE users MODIFY is_active BOOLEAN NOT NULL DEFAULT FALSE;
Type guard
// Validate column metadata before decoding:
fn is_non_null_bool(col: &Column) -> bool {
matches!(col.type_info().name(), "TINYINT(1)" | "BOOLEAN") && !col.nullable()
} Try / catch
// Panics are not catchable per-column; wrap whole row conversion:
let row = std::panic::catch_unwind(AssertUnwindSafe(|| ProxyRow::from_mysql_row(row, cols)))
.map_err(|_| DbErr::RecordNotFound("type mismatch decoding boolean"))?; Prevention
- Keep boolean columns NOT NULL with a default
- Use IFNULL in queries selecting nullable booleans
- Check type_info().name() strings against your pinned sqlx version
- Pin sqlx versions and review its MySQL type-naming changelog on upgrade
When it happens
Trigger: Executing a query whose BOOLEAN/TINYINT(1) column returns NULL, or where the decoded Rust type doesn't match what sqlx reports (e.g. using ProxyDatabase or custom row types, or newer sqlx MySQL type naming).
Common situations: Nullable boolean columns decoded via the proxy driver; sqlx version upgrades changing type_info().name() strings so the match arm fires for a column whose value decodes as a different type.
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
- Failed to get float
- Failed to get double
- Failed to get bytes
- Failed to get unsigned tiny integer
- Failed to get unsigned small integer
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/cddfbbe06412ea82.
Report an issue: GitHub.