{"record":{"id":"7c8b2223a8feac13","repo":"tursodatabase/turso","slug":"no-cursor-response-received-7c8b22","errorCode":null,"errorMessage":"No cursor response received","messagePattern":"No cursor response received","errorType":"exception","errorClass":"TursoServerlessException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Serverless.Client/HranaHttp.cs","lineNumber":92,"sourceCode":"            }\n\n            var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);\n            reader = new StreamReader(stream, Encoding.UTF8);\n\n            // The first non-empty line is the cursor response; the rest are cursor entries.\n            HranaCursorResponse? cursorResponse = null;\n            while (await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false) is { } line)\n            {\n                if (line.Trim() is not (\"\" or null) and var trimmed)\n                {\n                    cursorResponse = JsonSerializer.Deserialize<HranaCursorResponse>(trimmed, JsonOptions);\n                    break;\n                }\n            }\n\n            if (cursorResponse is null)\n            {\n                throw new TursoServerlessException(\"No cursor response received\");\n            }\n\n            var entries = ReadEntriesAsync(response, reader, cancellationToken);\n            response = null; // Ownership transferred to the entry enumerator.\n            reader = null;\n            return (cursorResponse, entries);\n        }\n        finally\n        {\n            reader?.Dispose();\n            response?.Dispose();\n            httpRequest.Dispose();\n        }\n    }\n\n    private static async IAsyncEnumerable<HranaCursorEntry> ReadEntriesAsync(\n        HttpResponseMessage response,\n        StreamReader reader,","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/dotnet/src/Turso.Serverless.Client/HranaHttp.cs#L74-L110","documentation":"On the NDJSON /v3/cursor protocol, the first non-empty line of the 2xx response must deserialize to HranaCursorResponse; remaining lines stream as entries. If the response stream ends with no non-empty line at all, this TursoServerlessException is thrown — the HTTP layer succeeded but delivered no data to parse.","triggerScenarios":"A 200 response with an entirely empty body; a connection that delivers headers then closes (dropped long-lived/streaming connection); buffering proxies that terminate or truncate streaming responses.","commonSituations":"Reverse proxies or corporate networks closing streaming connections; intermittent mobile/cloud networking dropping the body; server-side incident producing empty streams; timeouts between headers and first byte.","solutions":["Retry the cursor request: an empty stream after successful headers is usually a transient network/infrastructure fault.","Ensure the network path supports unbuffered streaming (test with curl -N against /v3/cursor).","Disable response buffering for this route in your proxy/gateway (nginx proxy_buffering off and equivalents).","Lengthen or remove first-byte read timeouts if intermediaries cut slow-starting streams."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// probe that the cursor endpoint streams data before building on it\nusing var resp = await httpClient.SendAsync(probeRequest, HttpCompletionOption.ResponseHeadersRead);\nusing var stream = await resp.Content.ReadAsStreamAsync();\nusing var sr = new StreamReader(stream);\nif (await sr.ReadLineAsync() is null) throw new InvalidOperationException(\"Cursor endpoint returned an empty stream\");","typeGuard":null,"tryCatchPattern":"catch (TursoServerlessException ex) when (ex.Message == \"No cursor response received\" && attempt < 3)\n{\n    await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));\n    continue; // empty stream after 2xx is almost always transient\n}","preventionTips":["Disable proxy buffering for streaming routes (e.g. nginx proxy_buffering off).","Set generous first-byte timeouts; streams may start slowly.","Retry empty streams once or twice before escalating; persistent emptiness means an infrastructure fault, not a query problem."],"tags":["dotnet","http","hrana-protocol","streaming","ndjson"],"backgroundTag":"empty-response-from-stream","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}