I have found these related issues/pull requests
Description
StatementHandle::column_nullable asks sqlite3_table_column_metadata() for a column's declared type and then calls CStr::from_ptr() on the result without checking for null:
let datatype = CStr::from_ptr(datatype);
SQLite sets that out-param to NULL when the column was declared with no type at all, which is legal:
CREATE TABLE users (device_id PRIMARY KEY, name TEXT);
So describing that table dereferences a null pointer and the process dies with SIGSEGV. Because the query!() family describes a live database during macro expansion, the process that dies is rustc itself:
error: rustc interrupted by SIGSEGV, printing backtrace
2 core::ffi::c_str::CStr::from_ptr
3 sqlx_sqlite::statement::handle::StatementHandle::column_nullable
4 sqlx_sqlite::connection::describe::describe
5 sqlx_sqlite::describe_blocking
6 sqlx_macros_core::database::impls::...::describe_blocking
7 sqlx_macros_core::query::expand_with
The practical effect is that a crate can't be compiled online or run cargo sqlx prepare at all if any table in the database has an untyped column, even when no query touches that table. An existing .sqlx cache keeps working, so offline builds are unaffected, but the cache can't be regenerated.
This is a regression in 0.9.0. Before #4088 the declared-type slot was passed as ptr::null_mut() and never read.
The sibling function column_decltype, twenty lines up, already null-checks the equivalent pointer from sqlite3_column_decltype().
Reproduction steps
cargo new sqlx-repro && cd sqlx-repro
cargo add tokio --features macros,rt-multi-thread
cargo add sqlx@0.9.0 --no-default-features --features runtime-tokio,sqlite,macros
sqlite3 repro.db "CREATE TABLE users (device_id PRIMARY KEY, name TEXT);"
src/main.rs:
#[tokio::main]
async fn main() {
let pool = sqlx::SqlitePool::connect(&std::env::var("DATABASE_URL").unwrap())
.await
.unwrap();
let row = sqlx::query!("SELECT device_id, name FROM users")
.fetch_optional(&pool)
.await
.unwrap();
println!("{:?}", row.map(|r| r.name));
}
DATABASE_URL="sqlite://repro.db" cargo build
Crashes with signal: 11, SIGSEGV. Changing device_id PRIMARY KEY to device_id TEXT PRIMARY KEY and rebuilding makes it compile, which isolates the untyped column as the trigger.
SQLx version
0.9.0
Enabled SQLx features
runtime-tokio, sqlite, macros (with default-features = false) is enough to reproduce
Database server and version
SQLite 3.51.3
Operating system
macOS
Rust version
rustc 1.96.1 (31fca3adb 2026-06-26)
I have found these related issues/pull requests
sqlite3_table_column_metadata()and dereferencing it unconditionally.INTEGER PRIMARY KEYinRETURNINGgoing back toOption). Different symptom.sqlx preparefails with error "unsupported type NULL of column #2" #1979 andunsupported type NULLerror only on my machine #3546: both reportunsupported type NULL of column #N. That's the error you should get for a column with no declared type. Right now you get a SIGSEGV before the error can be produced.Description
StatementHandle::column_nullableaskssqlite3_table_column_metadata()for a column's declared type and then callsCStr::from_ptr()on the result without checking for null:SQLite sets that out-param to NULL when the column was declared with no type at all, which is legal:
So describing that table dereferences a null pointer and the process dies with SIGSEGV. Because the
query!()family describes a live database during macro expansion, the process that dies isrustcitself:The practical effect is that a crate can't be compiled online or run
cargo sqlx prepareat all if any table in the database has an untyped column, even when no query touches that table. An existing.sqlxcache keeps working, so offline builds are unaffected, but the cache can't be regenerated.This is a regression in 0.9.0. Before #4088 the declared-type slot was passed as
ptr::null_mut()and never read.The sibling function
column_decltype, twenty lines up, already null-checks the equivalent pointer fromsqlite3_column_decltype().Reproduction steps
src/main.rs:DATABASE_URL="sqlite://repro.db" cargo buildCrashes with
signal: 11, SIGSEGV. Changingdevice_id PRIMARY KEYtodevice_id TEXT PRIMARY KEYand rebuilding makes it compile, which isolates the untyped column as the trigger.SQLx version
0.9.0
Enabled SQLx features
runtime-tokio,sqlite,macros(withdefault-features = false) is enough to reproduceDatabase server and version
SQLite 3.51.3
Operating system
macOS
Rust version
rustc 1.96.1 (31fca3adb 2026-06-26)