tursodatabase/turso · error · DatabaseError

HTTP error! status: ${response.status}

Error message

HTTP error! status: ${response.status}

What it means

DatabaseError thrown when the streaming /v3/cursor endpoint answers a non-2xx status; the runtime message interpolates the actual code (e.g. 'HTTP error! status: 401'). The client first tries to parse the response body as JSON and use its message field — only when the body is not parseable JSON (or has no message) does the generic status text survive.

Source

Thrown at serverless/javascript/src/protocol.ts:302

  let response: Response;
  try {
    response = await fetch(`${ctx.url}/v3/cursor`, buildFetchOptions(ctx, JSON.stringify(request), signal));
  } catch (error) {
    wrapAbortError(error);
  }

  if (!response.ok) {
    let errorMessage = `HTTP error! status: ${response.status}`;
    try {
      const errorBody = await response.text();
      const errorData = JSON.parse(errorBody);
      if (errorData.message) {
        errorMessage = errorData.message;
      }
    } catch {
      // If we can't parse the error body, use the default HTTP error message
    }
    throw new DatabaseError(errorMessage);
  }

  const reader = response.body?.getReader();
  if (!reader) {
    throw new DatabaseError('No response body');
  }

  const decoder = new TextDecoder();
  let buffer = '';
  let cursorResponse: CursorResponse | undefined;

  // First, read until we get the cursor response (first line)
  try {
    while (!cursorResponse) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });

View on GitHub (pinned to bad083fafb)

Solutions

  1. Verify the URL is the database's HTTPS endpoint and re-check the token: curl -i -X POST $URL/v3/pipeline -H "Authorization: Bearer $TOKEN" -d '{"baton":null,"requests":[]}'
  2. Refresh or rotate the token if the status is 401/403
  3. If a proxy intercepts the request, bypass it or fix its error responses so JSON bodies pass through

Example fix

// before
const db = connect({ url: "https://db.example.com", authToken: EXPIRED_TOKEN });
await db.all("SELECT 1"); // HTTP error! status: 401

// after
const token = await refreshPlatformToken();
const db = connect({ url: "https://db.example.com", authToken: token });
await db.all("SELECT 1");
Defensive patterns

Strategy: try-catch

Type guard

const isDatabaseError = (e: unknown): e is Error & { code?: string } =>
  e instanceof Error && e.name === "DatabaseError";

Try / catch

try {
  await db.all(sql);
} catch (e) {
  if (e instanceof Error && /HTTP error! status: (401|403)/.test(e.message)) {
    // auth problem: refresh the token and reconnect with it
  } else if (e instanceof Error && /HTTP error! status: 5\d\d/.test(e.message)) {
    // server/proxy problem: check status page, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: 401/403 from an invalid or expired authToken on any execute/batch call; 404 from a URL that is not a Turso SQL-over-HTTP endpoint; 5xx whose body is an HTML proxy error page, so JSON parsing fails and the fallback text is thrown.

Common situations: Expired Turso Cloud platform tokens; wrong or stale database URL after a rename/move; corporate proxies or WAFs returning HTML error pages on auth failure; pointing the client at an older self-hosted server with a different error body.

Related errors


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