tursodatabase/turso · error · TursoException
Unable to read native value bytes.
Error message
Unable to read native value bytes.
What it means
ReadBytes backs text and blob reads in the raw bindings: it first asks native code for the current value's byte count, and a negative count throws TursoException with this message. The native layer reporting no readable length for a value the type kind said was Text/Blob indicates the row is not currently valid — e.g. the statement was stepped past its data or is being disturbed concurrently.
Source
Thrown at bindings/dotnet/src/Turso.Raw/Public/TursoBindings.cs:406
if (bytes.Length == 0)
return bind(IntPtr.Zero);
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return bind(handle.AddrOfPinnedObject());
}
finally
{
handle.Free();
}
}
private static byte[] ReadBytes(TursoStatementHandle statement, UIntPtr index)
{
var length = TursoInterop.StatementRowValueBytesCount(statement, index);
if (length < 0)
throw new TursoException("Unable to read native value bytes.");
if (length == 0)
return [];
var ptr = TursoInterop.StatementRowValueBytesPtr(statement, index);
if (ptr == IntPtr.Zero)
throw new TursoException("Unable to read native value bytes.");
unsafe
{
var data = new ReadOnlySpan<byte>((void*)ptr, checked((int)length));
return data.ToArray();
}
}
private static UIntPtr ToNativeIndex(int index) => checked((UIntPtr)(ulong)index);
private static UIntPtr ToNativeLength(int length) => checked((UIntPtr)(ulong)length);
View on GitHub (pinned to 6c72522679)
Solutions
- Only call GetValue after Read() returned true for that row, and read all columns before stepping again.
- Keep one statement on one thread/task; serialize access.
- Confirm the native library version matches the bindings package.
- If it persists with correct sequencing, capture the SQL, column kinds, and library versions and report it upstream.
Example fix
// before
var value = TursoBindings.GetValue(statement, 0); // no row stepped yet -> TursoException
// after
if (TursoBindings.Read(statement))
{
var value = TursoBindings.GetValue(statement, 0);
} Defensive patterns
Strategy: validation
Validate before calling
// step to a row before reading any value
if (TursoBindings.Read(statement))
{
var value = TursoBindings.GetValue(statement, columnIndex);
} Try / catch
try { v = TursoBindings.GetValue(stmt, i); }
catch (TursoException ex) when (ex.Message == "Unable to read native value bytes.") { /* row not current or version skew */ } Prevention
- Read all columns immediately after the Read() that produced the row.
- One statement per thread; never step and read concurrently.
- Keep native and managed package versions aligned.
When it happens
Trigger: Calling TursoBindings.GetValue(statement, i) (which routes Text/Blob kinds through ReadBytes) when the statement has no current row — before a successful Read(), after Read() returned false/Done, or after another thread re-stepped the statement; also possible with a native library that does not match the bindings.
Common situations: Missing `if (TursoBindings.Read(stmt))` guard before GetValue; sharing one statement across tasks; reading values after finalizing; version skew between the native turso library and the managed package.
Related errors
- statement is invalid
- database is invalid
- Parameter index {index} is too large.
- Turso native call failed with status {status}.
- Turso sync ${operation} failed: ${message}
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20).
Data as JSON: /api/errors/08fdd487c9843957.
Report an issue: GitHub.