SeaQL/sea-orm · error
Failed to get double
Error message
Failed to get double
What it means
Panic when sea-orm-sync's SQLite driver cannot decode a "REAL" column into f64 while building a ProxyRow. Because SQLite does not enforce storage types, a REAL-declared column may physically contain text or integer values (or NULL) that sqlx refuses to decode into the expected f64.
Source
Thrown at sea-orm-sync/src/driver/sqlx_sqlite.rs:427
.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),
),
"BLOB" => Value::Bytes(
row.try_get::<Option<Vec<u8>>, _>(c.ordinal())
.expect("Failed to get bytes")
.map(Box::new),
),
#[cfg(feature = "with-chrono")]
"DATETIME" => {
use chrono::{DateTime, Utc};
View on GitHub (pinned to e29bcd1b41)
Solutions
- Normalize stored values: UPDATE t SET col = CAST(col AS REAL) WHERE typeof(col) != 'real'
- Decode as Option<f64> and treat NULL explicitly instead of non-Option try_get
- Enforce value hygiene at insert time by going through typed entity models rather than raw SQL
- Propagate the sqlx error with column name context instead of .expect
Example fix
// before
"REAL" => {
Value::Double(row.try_get(c.ordinal()).expect("Failed to get double"))
}
// after
"REAL" => {
Value::Double(row.try_get::<Option<f64>, _>(c.ordinal())
.expect("Failed to get double")
.unwrap_or(f64::NAN)) // or propagate with column context
} Defensive patterns
Strategy: validation
Validate before calling
// Verify REAL columns hold real storage class: // SELECT typeof(col), count(*) FROM t GROUP BY typeof(col);
Type guard
fn is_real_storage(type_of: &str) -> bool { type_of == "real" } Try / catch
let row = std::panic::catch_unwind(|| proxy_query(db)).unwrap_or_else(|_| fallback_row());
Prevention
- CAST non-real values to REAL after CSV/DB imports
- Insert floats via typed entity fields, not quoted raw SQL strings
- Declare columns REAL and add NOT NULL where possible
- Audit storage classes before ProxyRow reads
When it happens
Trigger: Reading a REAL column whose stored value has a non-real storage class (TEXT like '3.14', INTEGER, or NULL decoded into non-Option f64).
Common situations: Floats inserted as quoted strings by another tool or ORM; data imported from CSV where numbers stayed text; NULLs in legacy rows; columns repurposed after schema changes.
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 boolean
- Failed to get integer
- Failed to get big integer
- Failed to get string
- Failed to get bytes
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/159c1fa2cc2a26ea.
Report an issue: GitHub.