transact-rs/sqlx · warning
invalid column index: {}
Error message
invalid column index: {} What it means
In the SQLite driver, the check_col_idx! macro (sqlx-sqlite/src/statement/handle.rs) panics when a column index passed to a StatementHandle accessor cannot be converted to a C `c_int` — i.e. the index is negative or exceeds the c_int range. The sqlite3 C API takes an `int` column index, so any out-of-range Rust usize/i64 index is rejected before reaching SQLite. Reaching this means an internal caller used an invalid column ordinal.
Source
Thrown at sqlx-sqlite/src/statement/handle.rs:51
unsafe impl Send for StatementHandle {}
// Most of the getters below allocate internally, and unsynchronized access is undefined.
// unsafe impl !Sync for StatementHandle {}
macro_rules! expect_ret_valid {
($fn_name:ident($($args:tt)*)) => {{
let val = $fn_name($($args)*);
TryFrom::try_from(val)
// This likely means UB in SQLite itself or our usage of it;
// signed integer overflow is UB in the C standard.
.unwrap_or_else(|_| panic!("{}() returned invalid value: {val:?}", stringify!($fn_name)))
}}
}
macro_rules! check_col_idx {
($idx:ident) => {
c_int::try_from($idx).unwrap_or_else(|_| panic!("invalid column index: {}", $idx))
};
}
// might use some of this later
#[allow(dead_code)]
impl StatementHandle {
pub(super) fn new(ptr: NonNull<sqlite3_stmt>) -> Self {
Self(ptr)
}
#[inline]
pub(super) unsafe fn db_handle(&self) -> *mut sqlite3 {
// O(c) access to the connection handle for this statement handle
// https://sqlite.org/c3ref/db_handle.html
sqlite3_db_handle(self.0.as_ptr())
}
pub(crate) fn read_only(&self) -> bool {View on GitHub (pinned to 03af8bcc57)
Solutions
- Inspect the index value in the panic message and find the query/row access that produced it — usually a column accessed with an explicit numeric index out of bounds.
- Prefer name-based access: `row.try_get::<_, T>("column_name")` instead of positional indices.
- Check that the row/query being read matches the SQL executed (schema drift between prepared statement and access code).
- If it appears inside sqlx itself with a sane index, file an issue with a reproducer — it indicates a driver bug (index not validated before c_int conversion).
Example fix
// before
let name: String = row.try_get(7usize)?; // index out of range
// after
let name: String = row.try_get("name")?; Defensive patterns
Strategy: validation
Validate before calling
// Before positional access, bound-check the index against the row:
if idx >= row.columns().len() {
return Err(format!("column index {idx} out of range").into());
}
let val = row.try_get_unchecked::<_, String>(idx)?; Try / catch
// Use try_get (returns Result) rather than get, and catch/match the ColumnDecode/IndexOutOfBounds error:
match row.try_get::<_, String>(idx) {
Ok(v) => v,
Err(sqlx::Error::ColumnNotFound(n)) => fallback_for(n),
Err(e) => return Err(e.into()),
} Prevention
- Access columns by name, not positional index
- Derive indices from row.columns() lookups instead of hardcoding numbers
- Keep query SQL and row-access code in the same module/review scope so schema changes update both
When it happens
Trigger: Any SQLite code path (column name/type/value lookups in the driver) indexing a statement with a negative or huge index; realistically surfaced by driver bugs or by a `try_get`/`try_get_raw` call whose computed column index overflowed (e.g. from a corrupted ColumnIndex or row with an unexpectedly large index).
Common situations: Users typically see this indirectly: a get("col_name") resolving to an out-of-range ordinal after the query changed, or driver-level issues on very wide result sets; it is essentially an assertion that an internal invariant broke.
Related errors
- downcast to wrong DatabaseError type; original error: {self}
- downcast to wrong DatabaseError type; original error: {e}
- unimplemented!()
- extension entrypoint names passed to SQLite must not contain
- extension names passed to SQLite must not contain nul bytes
AI-assisted analysis of transact-rs/sqlx@03af8bcc57 (2026-09-03).
Data as JSON: /api/errors/a2131ec95a1921c8.
Report an issue: GitHub.