Hmbown/CodeWhale · error · Error

Cloudflare SQL request failed (${response.status}): ${body}

Error message

Cloudflare SQL request failed (${response.status}): ${body}

What it means

querySql POSTs the raw SQL text to SQL_ENDPOINT(accountId) with a Bearer CF_API_TOKEN; a non-ok response throws `Cloudflare SQL request failed (${response.status}): ${body}` including the first 500 chars of the body. The status plus embedded Cloudflare error body distinguishes auth, account, and query problems.

Source

Thrown at telemetry-ingest/scripts/report-active-installs.mjs:210

  lines.push("", "Caveats:");
  for (const caveat of COVERAGE_CAVEATS) {
    lines.push(`  - ${caveat}`);
  }
  return lines.join("\n");
}

async function querySql({ accountId, apiToken, sql, fetchImpl = fetch }) {
  const response = await fetchImpl(SQL_ENDPOINT(accountId), {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiToken}`,
      "content-type": "text/plain; charset=utf-8",
    },
    body: sql,
  });
  if (!response.ok) {
    const body = (await response.text()).slice(0, 500);
    throw new Error(`Cloudflare SQL request failed (${response.status}): ${body}`);
  }
  return response.json();
}

export async function main(argv = process.argv.slice(2), env = process.env) {
  const { days, json } = parseArgs(argv);
  const accountId = env.CF_ACCOUNT_ID?.trim();
  const apiToken = env.CF_API_TOKEN?.trim();
  if (!accountId || !apiToken) {
    throw new Error("CF_ACCOUNT_ID and CF_API_TOKEN are required");
  }
  const rows = rowsFromResponse(
    await querySql({ accountId, apiToken, sql: activeInstallsSql(days) }),
  );
  const newestEvent = newestEventFromResponse(
    await querySql({ accountId, apiToken, sql: freshnessSql() }),
  );
  const now = new Date();

View on GitHub (pinned to 8880682c63)

Solutions

  1. Read the embedded body first — Cloudflare error codes name the exact problem
  2. Re-create CF_API_TOKEN with the required read scope and access to the right account
  3. Verify CF_ACCOUNT_ID matches the account hosting the codewhale_telemetry dataset
  4. On 429 or transient 5xx, retry with backoff instead of immediately re-running

Example fix

# before
CF_ACCOUNT_ID=wrongaccount CF_API_TOKEN=noaccess node scripts/report-active-installs.mjs
# after
CF_ACCOUNT_ID=<id from dash> CF_API_TOKEN=<token with SQL read scope> node scripts/report-active-installs.mjs
Defensive patterns

Strategy: try-catch

Validate before calling

if (!env.CF_ACCOUNT_ID?.trim() || !env.CF_API_TOKEN?.trim()) {
  console.error('CF_ACCOUNT_ID and CF_API_TOKEN are required');
  process.exit(2);
}

Try / catch

try {
  await querySql({ accountId, apiToken, sql });
} catch (error) {
  const status = Number(error.message.match(/failed \((\d+)\)/)?.[1]);
  if (status === 429 || status >= 500) { await delay(backoffMs); return querySql({ accountId, apiToken, sql }); }
  throw error;
}

Prevention

When it happens

Trigger: 400 for invalid SQL syntax; 401/403 for a token missing the required read scope or that was revoked; 404 for a wrong CF_ACCOUNT_ID; 429 rate limiting.

Common situations: Token created without the Analytics/SQL read permission; account id copied from a different Cloudflare account; hand-edited SQL breaking syntax.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/46c8011dc4a9d9a8. Report an issue: GitHub.