tursodatabase/turso · error · TursoServerlessException

HTTP error! status: {(int)response.StatusCode}

Error message

HTTP error! status: {(int)response.StatusCode}

What it means

ExecutePipelineAsync posts the JSON pipeline to {baseUrl}/v3/pipeline and, on any non-2xx response, throws TursoServerlessException containing only the numeric HTTP status. The response body — which for Turso errors usually carries a JSON message — is not read on this path, so authentication, URL, and request-shape failures all surface as this one generic message.

Source

Thrown at bindings/dotnet/src/Turso.Serverless.Client/HranaHttp.cs:32

    /// <summary>HTTP header carrying the encryption key of an encrypted Turso Cloud database.</summary>
    internal const string EncryptionKeyHeader = "x-turso-encryption-key";

    private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);

    internal static async Task<HranaPipelineResponse> ExecutePipelineAsync(
        HttpClient httpClient,
        string baseUrl,
        string? authToken,
        string? remoteEncryptionKey,
        HranaPipelineRequest request,
        CancellationToken cancellationToken)
    {
        using var httpRequest = CreateRequest($"{baseUrl}/v3/pipeline", authToken, remoteEncryptionKey, request);

        using var response = await httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false);
        if (!response.IsSuccessStatusCode)
        {
            throw new TursoServerlessException($"HTTP error! status: {(int)response.StatusCode}");
        }

        var body = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
        return JsonSerializer.Deserialize<HranaPipelineResponse>(body, JsonOptions)
            ?? throw new TursoServerlessException("Empty pipeline response");
    }

    internal static async Task<(HranaCursorResponse Response, IAsyncEnumerable<HranaCursorEntry> Entries)> ExecuteCursorAsync(
        HttpClient httpClient,
        string baseUrl,
        string? authToken,
        string? remoteEncryptionKey,
        HranaCursorRequest request,
        CancellationToken cancellationToken)
    {
        var httpRequest = CreateRequest($"{baseUrl}/v3/cursor", authToken, remoteEncryptionKey, request);

        HttpResponseMessage? response = null;

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Verify the URL: https://<database>-<org>.turso.io (or your libsql endpoint) with no trailing path.
  2. Verify the auth token is present, current, and scoped to the database (turso db tokens create / show).
  3. For encrypted databases, supply the encryption key so the x-turso-encryption-key header is set.
  4. Reproduce with curl -H 'Authorization: Bearer <token>' -d @pipeline.json <url>/v3/pipeline to see the server's JSON error body, which this code path discards.

Example fix

// before: token null or stale -> 401 -> HTTP error! status: 401
var conn = new TursoConnection("Data Source=https://db-org.turso.io;AuthToken=");

// after: load the token from the environment
var conn = new TursoConnection($"Data Source=https://db-org.turso.io;AuthToken={Environment.GetEnvironmentVariable("TURSO_AUTH_TOKEN")}");
Defensive patterns

Strategy: try-catch

Validate before calling

// validate endpoint and token shape before first use
if (!Uri.TryCreate(baseUrl, UriKind.Absolute, out var u) || u.Scheme != Uri.UriSchemeHttps)
    throw new ArgumentException("baseUrl must be an https:// URL");
if (string.IsNullOrWhiteSpace(authToken))
    throw new InvalidOperationException("Auth token missing; set TURSO_AUTH_TOKEN");

Try / catch

catch (TursoServerlessException ex) when (ex.Message.Contains("status: 401"))
{
    // refresh the database token and rebuild the client/connection
}
catch (TursoServerlessException ex) when (ex.Message.Contains("status: 5"))
{
    // server incident: retry with backoff
}

Prevention

When it happens

Trigger: 401 from a missing/invalid/expired Bearer token; 404 from a wrong baseUrl or database name; 403 from a token without access to the database; 400 from a malformed pipeline body; 5xx from server incidents; missing x-turso-encryption-key header for an encrypted database.

Common situations: Expired Turso auth token in CI; URL copied without the https:// scheme or with a typo'd org/database slug; environment-specific token mix-ups; encrypted database accessed without the key; gateways returning 502 during maintenance.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/4a9559b5ab46a508. Report an issue: GitHub.