jackwener/OpenCLI · error · CommandExecutionError

Stack Exchange API HTTP ${res.status} for ${label}

Error message

Stack Exchange API HTTP ${res.status} for ${label}

What it means

fetchJson throws this CommandExecutionError when the Stack Exchange API responds with an HTTP status other than 200 and other than 404 (i.e. !res.ok). The message embeds the numeric status and the resource label; the hint points at wrong ids and the API's 300 requests/day per-IP quota. It surfaces server-side rejection the caller cannot fix by retrying blindly.

Source

Thrown at clis/stackoverflow/read.js:44

const SE_SITE = 'stackoverflow';
const SE_MAX_PAGE_SIZE = 100;

async function fetchJson(url, label) {
    let res;
    try {
        res = await fetch(url);
    } catch (e) {
        const detail = e instanceof Error ? e.message : String(e);
        throw new CommandExecutionError(
            `Network failure fetching ${label}: ${detail}`,
            'Check connectivity to api.stackexchange.com',
        );
    }
    if (res.status === 404) {
        throw new EmptyResultError(label, `${label} not found`);
    }
    if (!res.ok) {
        throw new CommandExecutionError(
            `Stack Exchange API HTTP ${res.status} for ${label}`,
            'Check the question id and quota (300/day per IP)',
        );
    }
    let json;
    try {
        json = await res.json();
    } catch (e) {
        const detail = e instanceof Error ? e.message : String(e);
        throw new CommandExecutionError(
            `Malformed JSON from Stack Exchange API for ${label}: ${detail}`,
            'The API returned a non-JSON body — likely a transient outage',
        );
    }
    if (json && json.error_id) {
        throw new CommandExecutionError(
            `Stack Exchange API error ${json.error_id} (${json.error_name}) for ${label}: ${json.error_message || ''}`,
            'Common causes: invalid filter, throttled, or quota exhausted',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the question id is a valid number; fix typos causing HTTP 400
  2. Wait for quota reset if near the 300/day per-IP limit, or register a Stack Exchange app/key to raise the quota
  3. Add backoff and avoid parallel bursts of requests
  4. For 5xx, retry later — likely a Stack Exchange-side outage (check status.stackexchange.com)

Example fix

// before
for (const id of ids) results.push(await getQuestion(id));

// after
for (const id of ids) {
  try {
    results.push(await getQuestion(id));
  } catch (e) {
    if (String(e.message).includes('HTTP 429')) await sleep(60000);
    results.push(await getQuestion(id));
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

function assertNumericId(id) {
  if (!/^\d+$/.test(String(id).trim())) {
    throw new TypeError(`Invalid id (would cause HTTP 400): ${id}`);
  }
}

Try / catch

async function getWithRateLimitGuard(fn, ...args) {
  try {
    return await fn(...args);
  } catch (e) {
    const m = /HTTP (\d+)/.exec(e?.message ?? '');
    if (m && (m[1] === '429' || m[1] === '502' || m[1] === '503')) {
      await new Promise(r => setTimeout(r, 30000));
      return fn(...args);
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: Any caller (qData, answersData, acceptedData, qCommentsData, ansCommentsData) receives e.g. HTTP 400 (malformed id/parameter), 429 or the API's quota exhaustion responses, 502/503 during Stack Exchange outages, or 5xx from an intermediary.

Common situations: Batch scripts looping over many questions exhausting the 300/day anonymous per-IP quota (especially shared office/VPN IPs); sending non-numeric ids causing 400; Stack Exchange maintenance windows returning 5xx; rate limiting from aggressive parallel requests.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/2909dd62cc14cf5f. Report an issue: GitHub.