koala73/worldmonitor · error · Error

CF Radar traffic anomalies API error: ${resp.status}

Error message

CF Radar traffic anomalies API error: ${resp.status}

What it means

fetchTrafficAnomalies calls the Cloudflare Radar traffic_anomalies endpoint (dateRange=7d, limit=100) and throws `CF Radar traffic anomalies API error: ${resp.status}` when the response status is not ok. This is the fatal, non-degradable guard for the traffic-anomalies portion of the internet-outages seed; any non-2xx aborts that dataset. The status code is the only diagnostic detail preserved.

Solutions

  1. Curl the exact URL with the seed's headers to see the status and response body directly.
  2. 401/403: fix token validity/scope; 429: space out runs or add exponential backoff; 5xx: retry and check Cloudflare status.
  3. Wrap the fetch in a small retry helper (2-3 attempts, backoff) for transient statuses before failing the seed.
  4. If the endpoint is optional to your use case, downgrade to a degraded result like fetchOptionalTargetLocations does instead of throwing.

Example fix

// before
const resp = await fetch(url, { headers, signal: AbortSignal.timeout(15_000) });
if (!resp.ok) throw new Error(`CF Radar traffic anomalies API error: ${resp.status}`);
// after
const resp = await fetch(url, { headers, signal: AbortSignal.timeout(15_000) });
if (!resp.ok) {
  if (resp.status === 429 || resp.status >= 500) return retryAfterBackoff(url, headers);
  throw new Error(`CF Radar traffic anomalies API error: ${resp.status} ${await resp.text().catch(() => '')}`);
}
Defensive patterns

Strategy: retry

Validate before calling

const pre = await fetch(`${CF_RADAR_BASE}/radar/traffic_anomalies?dateRange=7d&limit=100`, { headers });
console.log(`traffic_anomalies reachable: ${pre.ok} (${pre.status})`);

Try / catch

try {
  const anomalies = await fetchTrafficAnomalies(headers);
} catch (err) {
  const status = Number(err.message.match(/(\d+)$/)?.[1]);
  if (status === 429 || status >= 500) await retryWithBackoff(() => fetchTrafficAnomalies(headers), 3);
  else throw err;
}

Prevention

When it happens

Trigger: GET /radar/traffic_anomalies?dateRange=7d&limit=100 returns 401/403 (invalid or under-scoped API token), 429 (rate limit), or 5xx (Radar outage), caught by `if (!resp.ok) throw`.

Common situations: Token without the traffic-anomalies (Radar) scope; quota exhaustion from repeated 15s-timeout seed runs; Cloudflare-side incident returning 500/503.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/b75ffe0432596cc4. Report an issue: GitHub.

Appendix: source

Thrown at scripts/seed-internet-outages.mjs:284

    dateRangeStart: meta?.dateRange?.[0]?.startTime || '',
    dateRangeEnd: meta?.dateRange?.[0]?.endTime || '',
    topTargetLocations,
    _targetLocationsDegraded: targetSlice.degraded,
  };
}


async function fetchTrafficAnomalies(token) {
  const headers = {
    'User-Agent': CHROME_UA,
    ...(token ? { Authorization: `Bearer ${token}` } : {}),
  };

  const resp = await fetch(`${CF_RADAR_BASE}/radar/traffic_anomalies?dateRange=7d&limit=100`, {
    headers,
    signal: AbortSignal.timeout(15_000),
  });
  if (!resp.ok) throw new Error(`CF Radar traffic anomalies API error: ${resp.status}`);

  const result = requireRadarResult(await resp.json(), 'traffic anomalies');
  const raw = requireRadarArray(result, 'trafficAnomalies', 'traffic anomalies');

  const anomalies = raw.map((item) => {
    const coords = COUNTRY_COORDS[item.locationDetails?.code] || null;
    return {
      uuid: item.uuid || '',
      type: item.type || '',
      status: item.status || '',
      startDate: toEpochMs(item.startDate),
      endDate: toEpochMs(item.endDate),
      asn: item.asnDetails?.asn ? String(item.asnDetails.asn) : '',
      asnName: item.asnDetails?.name || '',
      locationCode: item.locationDetails?.code || '',
      locationName: item.locationDetails?.name || '',
      latitude: coords ? coords[0] : 0,
      longitude: coords ? coords[1] : 0,

View on GitHub (pinned to 7d06c8633d)