tursodatabase/turso · error · TursoServerlessException

Empty pipeline response

Error message

Empty pipeline response

What it means

After a successful (2xx) pipeline response, the body is deserialized into HranaPipelineResponse; a null result throws TursoServerlessException with this message. A null only arises when the body is empty/whitespace or the literal JSON null — a healthy pipeline endpoint always returns an object with a results array.

Source

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

    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;
        StreamReader? reader = null;
        try
        {
            response = await httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Confirm the baseUrl actually targets the database's HTTP endpoint (test the same pipeline with curl).
  2. Bypass or configure intermediaries (proxy, gateway) that may strip bodies; check their logs.
  3. Retry once — empty 200s from infrastructure glitches are usually transient.
  4. If reproducible only through your stack, capture the raw response (status, headers, length) to pinpoint which hop emptied it.
Defensive patterns

Strategy: retry

Validate before calling

// verify the endpoint serves the pipeline protocol before relying on it
using var probe = new HttpClient();
var resp = await probe.PostAsync(url + "/v3/pipeline", new StringContent("{\"requests\":[]}", Encoding.UTF8, "application/json"));
var body = await resp.Content.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(body)) throw new InvalidOperationException("Endpoint returned an empty body; check baseUrl/proxy");

Try / catch

catch (TursoServerlessException ex) when (ex.Message == "Empty pipeline response")
{
    if (attempt < 2) { await Task.Delay(backoff); continue; } // transient empty 200
    throw; // persistent: wrong endpoint or body-stripping intermediary
}

Prevention

When it happens

Trigger: A 200 response with an empty body: misrouted baseUrl (static host, wrong port), a proxy or gateway that swallowed the body, health-check responses, or the literal string null from a misbehaving intermediary.

Common situations: Corporate proxies or API gateways rewriting responses; baseUrl pointing at a dashboard/static domain instead of the database endpoint; rare server-side incidents returning empty 200s.

Related errors


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