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

  1. Bypass or reconfigure proxies/CDNs in front of the database (disable response buffering, raise stream limits)
  2. Check gateway limits — response timeout and max response size — against long-running query streams
  3. 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

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


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/211bf0582665cdfc. Report an issue: GitHub.