SeaQL/sea-orm · error
Failed to get string
Error message
Failed to get string
What it means
Panic when sea-orm-sync's SQLite driver cannot decode a "TEXT" column into Option<String> while building a ProxyRow. Although the target is an Option, sqlx still fails when the underlying storage class is not text (e.g. BLOB or numeric) under a TEXT-typed column, thanks to SQLite's dynamic typing.
Source
Thrown at sea-orm-sync/src/driver/sqlx_sqlite.rs:432
"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};
Value::ChronoDateTimeUtc(
row.try_get::<Option<DateTime<Utc>>, _>(c.ordinal())
.expect("Failed to get timestamp")
.map(Box::new),
)View on GitHub (pinned to e29bcd1b41)
Solutions
- Normalize storage: UPDATE t SET col = CAST(col AS TEXT) WHERE typeof(col) != 'text'
- Verify with SELECT typeof(col), count(*) GROUP BY typeof(col) to find offending rows
- Insert data through typed entity models so SQLite affinity converts values to text
- Propagate the sqlx error with column context instead of .expect and fall back to reading bytes
Example fix
// before
"TEXT" => Value::String(
row.try_get::<Option<String>, _>(c.ordinal())
.expect("Failed to get string")
.map(Box::new),
),
// after
"TEXT" => Value::String(
row.try_get::<Option<String>, _>(c.ordinal())
.unwrap_or_else(|e| panic!("Failed to get string for col {}: {}", c.name(), e))
.map(Box::new),
) // better: fall back to CAST(col AS TEXT) at query time Defensive patterns
Strategy: validation
Validate before calling
// Verify TEXT columns hold text storage class: // SELECT typeof(col), count(*) FROM t GROUP BY typeof(col);
Type guard
fn is_text_storage(type_of: &str) -> bool { type_of == "text" } Try / catch
let row = std::panic::catch_unwind(|| proxy_query(db)).unwrap_or_else(|_| fallback_row());
Prevention
- CAST blobs/numbers to TEXT when a column is declared TEXT
- Avoid inserting bytes into text columns via other drivers
- Use typed entity models for string fields
- Run a typeof() audit after each data import
When it happens
Trigger: Reading a TEXT column whose stored value has storage class BLOB or INTEGER/REAL that sqlx won't decode into Option<String>, or other sqlx-level decode errors on the column.
Common situations: Strings inserted as BLOBs (e.g. via bytes buffers in another driver); columns declared TEXT but holding numeric data inserted via raw SQL; corruption or mixed-type data imported from other databases.
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 double
- Failed to get bytes
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/39cf417878cd6a1a.
Report an issue: GitHub.