Hmbown/CodeWhale · error · Error
CF_ACCOUNT_ID and CF_API_TOKEN are required
Error message
CF_ACCOUNT_ID and CF_API_TOKEN are required
What it means
main() requires Cloudflare credentials before issuing any D1 queries. It reads CF_ACCOUNT_ID and CF_API_TOKEN from the environment, trims them, and throws if either is missing or empty, because the script cannot authenticate to the Cloudflare API without both.
Solutions
- Export both variables before running: CF_ACCOUNT_ID=... CF_API_TOKEN=... node script.
- Add them to your .env / CI secret store and ensure it is actually loaded.
- Check for typos and whitespace: `echo "[$CF_ACCOUNT_ID]"` should show non-empty content.
- Use a Cloudflare API token scoped to D1 read for the correct account.
Example fix
// before node telemetry-ingest/scripts/report-active-installs.mjs --days 30 // after CF_ACCOUNT_ID=abc123 CF_API_TOKEN=xxxx node telemetry-ingest/scripts/report-active-installs.mjs --days 30
Defensive patterns
Strategy: validation
Validate before calling
if (!process.env.CF_ACCOUNT_ID?.trim() || !process.env.CF_API_TOKEN?.trim()) { console.error("Set CF_ACCOUNT_ID and CF_API_TOKEN first"); process.exit(1); } Try / catch
try { await main(); } catch (e) { if (e.message.includes("CF_ACCOUNT_ID")) { console.error("Missing Cloudflare credentials: export CF_ACCOUNT_ID and CF_API_TOKEN"); process.exitCode = 2; } else throw e; } Prevention
- Load .env before running (dotenv or `set -a; source .env; set +a`).
- Add a preflight credential check in CI before invoking the script.
- Use consistent variable names across scripts.
- Echo variables (masked) to confirm they are non-empty in CI.
When it happens
Trigger: Running `report-active-installs` without exporting CF_ACCOUNT_ID or CF_API_TOKEN, or with either set to whitespace-only or empty string.
Common situations: Forgetting to source an .env file; running under CI where secrets were not injected; typo in variable name (e.g. CLOUDFLARE_API_TOKEN); shell where `export` was omitted.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- a CNB access token is not configured in the Codewhale…
- api_key cannot be empty string
- CODEWHALE_HOME / user home is unavailable
- Custom endpoint credentials for
- external credential access is disabled for
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/82deb051becac09d.
Report an issue: GitHub.
Appendix: source
Thrown at telemetry-ingest/scripts/report-active-installs.mjs:220
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();
if (json) {
process.stdout.write(
`${JSON.stringify(
{
metric: "observed_active_installs",
timezone: "UTC",
days,
rows,
trend: trendSummary(rows, days, now),
freshness: {View on GitHub (pinned to 433685b202)