tursodatabase/turso · error · IndexOutOfRangeException
column {name} not found
Error message
column {name} not found What it means
TursoDataReader.GetOrdinal(name) scans the current statement's result columns via GetName and throws IndexOutOfRangeException when no column matches the given name. The comparison is ordinal ('==' on strings), so it is case-sensitive and whitespace-sensitive, unlike some ADO.NET providers that fall back to case-insensitive matching. It only sees columns actually projected by the executed statement, not all table columns.
Source
Thrown at bindings/dotnet/src/Turso.Data/TursoDataReader.cs:182
return TursoBindings.GetValue(_statement, ordinal).IntValue;
}
public override string GetName(int ordinal)
{
return TursoBindings.GetName(_statement, ordinal);
}
public override int GetOrdinal(string name)
{
var fields = TursoBindings.GetFieldCount(_statement);
for (var i = 0; i < fields; i++)
{
var columnName = TursoBindings.GetName(_statement, i);
if (columnName == name)
return i;
}
throw new IndexOutOfRangeException($"column {name} not found");
}
public override string GetString(int ordinal)
{
return TursoBindings.GetValue(_statement, ordinal).StringValue;
}
public override object GetValue(int ordinal)
{
var value = TursoBindings.GetValue(_statement, ordinal);
return value.ValueType switch
{
TursoValueType.Null or TursoValueType.Empty => DBNull.Value,
TursoValueType.Integer => value.IntValue,
TursoValueType.Real => value.RealValue,
TursoValueType.Text => value.StringValue,
TursoValueType.Blob => value.BlobValue,
_ => throw new ArgumentOutOfRangeException()View on GitHub (pinned to 6c72522679)
Solutions
- Use the exact column name as returned by the query, including casing (check with reader.GetName(i) for i in 0..FieldCount-1).
- Prefer explicit column lists in SELECT instead of '*' so names are stable across schema changes.
- Do the case-insensitive fallback yourself: enumerate names once and match with StringComparison.OrdinalIgnoreCase.
- Confirm the reader is on the statement you think it is (call NextResult() as needed in batch scenarios).
Example fix
// before
var idx = reader.GetOrdinal("UserName"); // column is actually 'username'
// after
var idx = Enumerable.Range(0, reader.FieldCount)
.First(i => string.Equals(reader.GetName(i), "UserName", StringComparison.OrdinalIgnoreCase)); Defensive patterns
Strategy: validation
Validate before calling
int? FindColumn(DbDataReader reader, string name)
{
for (var i = 0; i < reader.FieldCount; i++)
if (string.Equals(reader.GetName(i), name, StringComparison.OrdinalIgnoreCase))
return i;
return null;
} Try / catch
try { idx = reader.GetOrdinal(name); } catch (IndexOutOfRangeException) { /* log available columns, rethrow as schema-drift error */ } Prevention
- Prefer explicit SELECT column lists over '*' so names are stable.
- Cache ordinals once per result shape instead of looking up per row.
- Add schema-drift smoke tests that assert expected column names.
When it happens
Trigger: Calling GetOrdinal("UserName") when the query returned "username"; calling GetOrdinal after a SELECT that aliases or omits the column; calling it when the reader is positioned on a statement whose result set has different columns (multi-statement batches); passing a name with stray whitespace.
Common situations: SELECT * queries after a schema migration renamed/dropped a column; column aliases in the SQL differing from what the reader code expects; code shared between database engines with different identifier casing; ordinal lookups after DDL statements that return zero columns.
Related errors
- Unknown column: {column}
- The data is NULL at ordinal {ordinal}.
- Column name {name} is ambiguous between {column1} and {colum
- Column {name} was not found.
- No data exists for the row/column.
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20).
Data as JSON: /api/errors/1194c0cb910ff83f.
Report an issue: GitHub.