tursodatabase/turso · error · DatabaseError
No cursor response received
Error message
No cursor response received
What it means
DatabaseError thrown when the /v3/cursor response body stream ends (or yields no newline-terminated line) before the first line — the CursorResponse JSON that carries the baton — arrives. The session cannot continue without that baton, so the request fails and the session resets its baton to null for a clean retry.
Source
Thrown at serverless/javascript/src/protocol.ts:340
const newlineIndex = buffer.indexOf('\n');
if (newlineIndex !== -1) {
const line = buffer.slice(0, newlineIndex).trim();
buffer = buffer.slice(newlineIndex + 1);
if (line) {
cursorResponse = JSON.parse(line);
break;
}
}
}
} catch (error) {
reader.releaseLock();
wrapAbortError(error);
}
if (!cursorResponse) {
reader.releaseLock();
throw new DatabaseError('No cursor response received');
}
async function* parseEntries(): AsyncGenerator<CursorEntry> {
try {
// Process any remaining data in the buffer
let newlineIndex;
while ((newlineIndex = buffer.indexOf('\n')) !== -1) {
const line = buffer.slice(0, newlineIndex).trim();
buffer = buffer.slice(newlineIndex + 1);
if (line) {
yield JSON.parse(line) as CursorEntry;
}
}
// Continue reading from the stream
while (true) {
let readResult: ReadableStreamReadResult<Uint8Array>;View on GitHub (pinned to bad083fafb)
Solutions
- Bypass or reconfigure proxies/CDNs in front of the database (disable response buffering, raise stream limits)
- Check gateway limits — response timeout and max response size — against long-running query streams
- Retry the query: this is usually transient and the session baton was already reset, so the next request starts clean
Example fix
# before — nginx buffers and can cut the chunked cursor stream
proxy_buffering on;
# after — pass streaming responses straight through
location /v3/ {
proxy_buffering off;
proxy_read_timeout 300s;
} Defensive patterns
Strategy: retry
Try / catch
try {
await db.all(sql);
} catch (e) {
if (e instanceof Error && e.message === "No cursor response received") {
await new Promise((r) => setTimeout(r, 200));
await db.all(sql); // stream was cut; session baton was reset, retry is safe
} else throw e;
} Prevention
- Disable response buffering on any proxy in front of the database
- Connect directly to the database URL where possible instead of through gateways
- Watch gateway response timeouts — they silently cut long streams
When it happens
Trigger: A proxy or load balancer closing or truncating the chunked response before the first line; response buffering that splits the stream; the server crashing after sending headers but before the first data chunk; a first chunk containing no complete line.
Common situations: CDN/nginx buffering or response-size limits cutting chunked responses; API gateways with aggressive response timeouts; local dev proxies that don't forward chunked transfer encoding; platform incidents that kill in-flight streams.
Related errors
- No response body
- reader is null
- getAllRows: exceeded ${MAX_IO_RETRIES} IO retries
- HTTP request failed: ${e instanceof Error ? e.message : Stri
- Query timed out
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/211bf0582665cdfc.
Report an issue: GitHub.