{"record":{"id":"46c8011dc4a9d9a8","repo":"Hmbown/CodeWhale","slug":"cloudflare-sql-request-failed-response-status-body","errorCode":null,"errorMessage":"Cloudflare SQL request failed (${response.status}): ${body}","messagePattern":"Cloudflare SQL request failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"telemetry-ingest/scripts/report-active-installs.mjs","lineNumber":210,"sourceCode":"  lines.push(\"\", \"Caveats:\");\n  for (const caveat of COVERAGE_CAVEATS) {\n    lines.push(`  - ${caveat}`);\n  }\n  return lines.join(\"\\n\");\n}\n\nasync function querySql({ accountId, apiToken, sql, fetchImpl = fetch }) {\n  const response = await fetchImpl(SQL_ENDPOINT(accountId), {\n    method: \"POST\",\n    headers: {\n      Authorization: `Bearer ${apiToken}`,\n      \"content-type\": \"text/plain; charset=utf-8\",\n    },\n    body: sql,\n  });\n  if (!response.ok) {\n    const body = (await response.text()).slice(0, 500);\n    throw new Error(`Cloudflare SQL request failed (${response.status}): ${body}`);\n  }\n  return response.json();\n}\n\nexport async function main(argv = process.argv.slice(2), env = process.env) {\n  const { days, json } = parseArgs(argv);\n  const accountId = env.CF_ACCOUNT_ID?.trim();\n  const apiToken = env.CF_API_TOKEN?.trim();\n  if (!accountId || !apiToken) {\n    throw new Error(\"CF_ACCOUNT_ID and CF_API_TOKEN are required\");\n  }\n  const rows = rowsFromResponse(\n    await querySql({ accountId, apiToken, sql: activeInstallsSql(days) }),\n  );\n  const newestEvent = newestEventFromResponse(\n    await querySql({ accountId, apiToken, sql: freshnessSql() }),\n  );\n  const now = new Date();","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/telemetry-ingest/scripts/report-active-installs.mjs#L192-L228","documentation":"querySql() POSTs a SQL statement to the Cloudflare D1 HTTP endpoint and throws when the HTTP response status is not OK, embedding the status code and the first 500 characters of the response body so the API-side error (auth, bad SQL, account issues) is visible.","triggerScenarios":"Any D1 HTTP query where response.ok is false: invalid/expired CF_API_TOKEN (401/403), wrong account ID (404), malformed SQL (400), rate limits (429), or D1 unavailable (5xx).","commonSituations":"Expired or wrongly-scoped API token; account ID copied from the wrong resource; SQL syntax error after a schema change; network proxy returning an HTML error page.","solutions":["Read the embedded body in the message — it usually states the exact API error.","Verify CF_API_TOKEN is valid and has D1 (account-level) read permission; regenerate if expired.","Verify CF_ACCOUNT_ID matches the account owning the database.","Run the SQL manually against the D1 console to catch syntax/schema errors.","Retry with backoff if status is 429 or 5xx."],"exampleFix":"// before\nconst res = await fetch(url, { method: \"POST\", headers, body: sql });\n// after\nconst res = await fetch(url, { method: \"POST\", headers, body: sql });\nif (res.status === 429 || res.status >= 500) await new Promise(r => setTimeout(r, 2000)); // retry once","handlingStrategy":"retry","validationCode":"if (!env.CF_ACCOUNT_ID?.trim() || !env.CF_API_TOKEN?.trim()) throw new Error(\"credentials missing before request\");","typeGuard":null,"tryCatchPattern":"try { await querySql(opts); } catch (e) { if (/failed \\((\\d{3})\\)/.test(e.message)) { const status = +RegExp.$1; if (status === 429 || status >= 500) retryWithBackoff(); } throw e; }","preventionTips":["Rotate and scope API tokens before expiry; test with a cheap query first.","Verify account ID against the dashboard URL.","Validate SQL against the D1 console before shipping.","Add bounded retry with backoff for 429/5xx."],"tags":["cloudflare","d1","http","api","sql"],"backgroundTag":"http-error-response","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}