SeaQL/sea-orm · error
Failed to get unsigned tiny integer
Error message
Failed to get unsigned tiny integer
What it means
For MySQL columns named 'TINYINT UNSIGNED', the proxy row decoder calls row.try_get(c.ordinal()).expect("Failed to get unsigned tiny integer"), assuming the value decodes as u8. A NULL value, or a mismatch between the reported type-info name and the actual stored Rust type, makes try_get fail and the expect panics.
Source
Thrown at src/driver/sqlx_mysql.rs:401
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(
row.try_get(c.ordinal())
.expect("Failed to get tiny integer"),
),
"SMALLINT" => Value::SmallInt(View on GitHub (pinned to e29bcd1b41)
Solutions
- Avoid NULLs on these columns (NOT NULL constraint) or decode as Option<u8> with a defined default.
- Use SQL COALESCE/IFNULL to substitute 0 for NULL unsigned values.
- Verify the type-info name strings against your sqlx version's MySQL type naming.
- Convert the try_get error into a DbErr instead of panicking with expect.
Example fix
// before
"TINYINT UNSIGNED" => Value::TinyUnsigned(
row.try_get(c.ordinal()).expect("Failed to get unsigned tiny integer")),
// after
"TINYINT UNSIGNED" => Value::TinyUnsigned(
row.try_get::<Option<u8>, _>(c.ordinal())
.map_err(|e| DbErr::Query(RuntimeErr::Protocol(e.to_string())))?
.unwrap_or(0)), Defensive patterns
Strategy: validation
Validate before calling
-- Ensure unsigned tinyint columns cannot be NULL: ALTER TABLE items MODIFY retry_count TINYINT UNSIGNED NOT NULL DEFAULT 0;
Type guard
fn decodable_u8(col: &Column) -> bool {
col.type_info().name() == "TINYINT UNSIGNED" && !col.nullable()
} Try / catch
let converted = std::panic::catch_unwind(AssertUnwindSafe(|| ProxyRow::from_mysql_row(row, cols)));
if converted.is_err() { return Err(DbErr::Query(RuntimeErr::Protocol("unsigned tinyint decode failed".into()))); } Prevention
- Add NOT NULL constraints to unsigned columns
- Coalesce NULL unsigned values to 0 in SELECTs
- Verify sqlx version compatibility with sea-orm's type-name matching
- Test proxy decoding against real MySQL schemas in CI
When it happens
Trigger: Selecting a nullable TINYINT UNSIGNED column through the sqlx MySQL proxy path; type_info().name() returns 'TINYINT UNSIGNED' but the underlying value cannot be decoded as u8 (NULL or driver representation change).
Common situations: Migrating sqlx versions where unsigned column representations changed; proxy/mock databases returning rows whose declared types don't match their payload types.
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 boolean
- Failed to get unsigned small integer
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/50eae7a2e0bdc1a7.
Report an issue: GitHub.