tursodatabase/turso · error · InvalidOperationException
The data reader has no result sets.
Error message
The data reader has no result sets.
What it means
The remote reader keeps a list of RemoteStatementResult sets; the CurrentResult property throws InvalidOperationException when that list is empty. Nearly every member (FieldCount, HasRows, Read, GetName, GetValue) flows through CurrentResult, so a reader constructed with zero result payloads is unusable rather than empty.
Source
Thrown at bindings/dotnet/src/Turso.Data/TursoRemoteDataReader.cs:297
{
return cancellationToken.IsCancellationRequested
? Task.FromCanceled<bool>(cancellationToken)
: Task.FromResult(Read());
}
public override int Depth => 0;
public override IEnumerator GetEnumerator()
{
return new DbEnumerator(this, closeReader: false);
}
private RemoteStatementResult CurrentResult
{
get
{
if (_results.Count == 0)
throw new InvalidOperationException("The data reader has no result sets.");
return _results[_resultIndex];
}
}
private bool HasCurrentRow => _rowIndex >= 0 && _rowIndex < CurrentResult.Rows.Count;
private RemoteResponseValue CurrentValue(int ordinal)
{
EnsureOpen();
if (!HasCurrentRow)
throw new InvalidOperationException("No current row. Call Read before accessing values.");
ValidateOrdinal(ordinal);
var row = CurrentResult.Rows[_rowIndex];
if (ordinal >= row.Count)
throw new IndexOutOfRangeException($"column ordinal {ordinal} is out of range");
View on GitHub (pinned to 6c72522679)
Solutions
- Use ExecuteNonQuery for INSERT/UPDATE/DELETE/DDL instead of a reader.
- If you must branch, decide based on the statement kind or the command API you called, not on reader.FieldCount (which itself throws here).
- When running batches, iterate with NextResult() and treat each set according to whether it has columns.
- Avoid manually constructing RemoteStatementResult lists with zero entries in tests and harnesses.
Example fix
// before using var reader = command.ExecuteReader(); // INSERT statement, no result set Console.WriteLine(reader.FieldCount); // throws: no result sets // after int affected = command.ExecuteNonQuery(); Console.WriteLine(affected);
Defensive patterns
Strategy: validation
Validate before calling
// choose the API by statement kind before executing
bool isQuery = sql.TrimStart().StartsWith("SELECT", StringComparison.OrdinalIgnoreCase);
if (isQuery) { using var r = command.ExecuteReader(); /* ... */ }
else { var n = command.ExecuteNonQuery(); } Try / catch
try { var fc = reader.FieldCount; }
catch (InvalidOperationException) { /* statement produced no result set; nothing to read */ } Prevention
- Use ExecuteNonQuery for DML/DDL and readers only for queries.
- Keep batches to one statement kind, or walk result sets with NextResult().
- Never build readers with empty result lists in tests or custom transports.
When it happens
Trigger: Calling ExecuteReader-style APIs on a statement that produces no result payload (INSERT, UPDATE, DELETE, CREATE TABLE, PRAGMA without rows) and then touching any reader property; a code path that constructs TursoRemoteDataReader with an empty results list; an empty or comment-only batch.
Common situations: Generic helper methods that always use ExecuteReader regardless of statement kind; batches mixing DDL and SELECT where the first result has no columns; porting code from SqliteClient where a reader for a non-query is merely empty.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Turso batch execution is currently supported only for remote
- SqliteBlob requires an open connection.
- TursoBatchCommand only supports CommandType.Text.
- Batch command must be a TursoBatchCommand.
- Unknown column: {column}
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20).
Data as JSON: /api/errors/da56b714c1d7decb.
Report an issue: GitHub.