tursodatabase/turso · error · TursoException

Turso native call failed with status {status}.

Error message

Turso native call failed with status {status}.

What it means

ThrowIfError is the shared exit check for all native P/Invoke calls in TursoBindings: statuses Ok/Done/Row pass, an error-string pointer produces a native message, and everything else throws TursoException carrying the raw status enum name (e.g. Busy, Io, Interrupt). This variant appears when native code fails without returning an error string, so the status code is all the diagnostics you get.

Source

Thrown at bindings/dotnet/src/Turso.Raw/Public/TursoBindings.cs:433

        {
            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);

    private static void ThrowIfError(TursoStatusCode status, IntPtr errorPtr, string? messagePrefix = null)
    {
        if (errorPtr != IntPtr.Zero)
            ThrowException(errorPtr, messagePrefix);

        if (status is TursoStatusCode.Ok or TursoStatusCode.Done or TursoStatusCode.Row)
            return;

        throw new TursoException($"Turso native call failed with status {status}.");
    }

    private static void ThrowException(IntPtr errorPtr, string? messagePrefix = null)
    {
        var errorMessage = Marshal.PtrToStringUTF8(errorPtr);
        var exception = new TursoException($"{messagePrefix}{errorMessage ?? "Internal error"}");
        TursoInterop.FreeString(errorPtr);
        throw exception;
    }

    private sealed class NativeUtf8String : IDisposable
    {
        private NativeUtf8String(IntPtr pointer) => Pointer = pointer;

        public IntPtr Pointer { get; private set; }

        public static NativeUtf8String From(string? value)
        {

View on GitHub (pinned to 6c72522679)

Solutions

  1. Read the status name from the message to classify: Busy -> retry after backoff; Io -> check path, permissions, disk; Interrupt/Oom -> inspect app state and resources.
  2. For Busy, wrap statements in a bounded retry with exponential backoff and consider a busy timeout if the layer exposes one.
  3. Verify the database path is readable/writable and the volume has space.
  4. Ensure the native library shipped with the bindings version you reference (no partial upgrades).

Example fix

// before
var stmt = TursoBindings.PrepareStatement(db, sql); // may throw: Turso native call failed with status Busy.

// after
TursoStatementHandle stmt;
for (var attempt = 0; ; attempt++)
{
    try { stmt = TursoBindings.PrepareStatement(db, sql); break; }
    catch (TursoException ex) when (attempt < 3 && ex.Message.Contains("Busy"))
    {
        Thread.Sleep(100 << attempt);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight the conditions behind the common statuses
if (!File.Exists(path)) throw new FileNotFoundException(path);
if (!HasWriteAccess(Path.GetDirectoryName(path))) throw new UnauthorizedAccessException(path);

Try / catch

catch (TursoException ex)
{
    if (ex.Message.Contains("Busy") && attempt < maxRetries) { await Task.Delay(backoff); continue; }
    if (ex.Message.Contains("Io")) { /* verify path, permissions, disk space; do not retry blindly */ }
    throw;
}

Prevention

When it happens

Trigger: Any wrapped native operation failing silently: opening a database file you cannot read/write (Io), a locked/busy database during write contention (Busy), interrupted execution, out-of-memory conditions, or an unrecognized status from a version-mismatched native library.

Common situations: Concurrent writers on the same file causing busy failures; wrong file permissions or a read-only mount; disk full; container memory limits; partial upgrades where the native library returns statuses the bindings do not map.

Related errors


AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20). Data as JSON: /api/errors/7e3cb56671719b1e. Report an issue: GitHub.