jackwener/OpenCLI · error · CommandExecutionError

stack exchange API error: ${data.error_message || data.error

Error message

stack exchange API error: ${data.error_message || data.error_name}

What it means

The Stack Exchange API responded with valid JSON that carries an error_id, meaning the API itself rejected the request (e.g. no site matched, invalid parameter, throttled). seFetch surfaces error_message/error_name verbatim. The second argument hints that opening the URL in a browser shows the canonical error context.

Source

Thrown at clis/stackoverflow/utils.js:77

    } catch (error) {
        throw new CommandExecutionError(`stack exchange request failed: ${error?.message || error}`);
    }
    if (resp.status === 429) {
        throw new CommandExecutionError('stack exchange returned HTTP 429 (rate limited)', 'Wait a few seconds and retry, or lower --limit.');
    }
    if (!resp.ok) {
        let body = '';
        try { body = (await resp.json())?.error_message || ''; } catch { /* ignore */ }
        throw new CommandExecutionError(`stack exchange HTTP ${resp.status}: ${body || resp.statusText}`);
    }
    let data;
    try {
        data = await resp.json();
    } catch (error) {
        throw new CommandExecutionError(`stack exchange returned malformed JSON: ${error?.message || error}`);
    }
    if (data?.error_id) {
        throw new CommandExecutionError(
            `stack exchange API error: ${data.error_message || data.error_name}`,
            'Inspect the URL in a browser for the canonical error context.',
        );
    }
    return data;
}

/** Convert SE epoch seconds to YYYY-MM-DD. */
export function epochToDate(value) {
    if (value == null || value === '') return '';
    const n = Number(value);
    if (!Number.isFinite(n) || n <= 0) return '';
    return new Date(n * 1000).toISOString().slice(0, 10);
}

/** Throw EmptyResultError when an /items array is empty. */
export function ensureItems(data, label) {
    const items = Array.isArray(data?.items) ? data.items : [];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read error_message in the thrown message and fix the offending parameter (usually `site`)
  2. Check daily quota: anonymous requests are limited to 300/day per IP; register an app key to raise it to 10,000
  3. Open the failing request URL in a browser to see the full API error payload
  4. Verify the site parameter against https://api.stackexchange.com/2.3/sites
Defensive patterns

Strategy: try-catch

Validate before calling

// no meaningful pre-call validation; validate parameters instead:
if (!/^[a-z]+$/.test(site)) throw new Error(`invalid site: ${site}`);

Try / catch

try {
  const data = await seFetch(url);
} catch (e) {
  if (/stack exchange API error/.test(e.message)) {
    if (/throttl|quota/i.test(e.message)) await sleep(backoff);
    else console.error('Fix request params (usually `site`):', e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: Invalid site parameter (site=nonexistent), missing/invalid key with exceeded anonymous quota (error_id=402 throttle_violation), malformed request parameters rejected by the API.

Common situations: Typo'd site name (e.g. site=stackoverflow vs site=stackoverflow needing correct api_site_parameter), anonymous 300-requests-per-day quota exhausted on shared IP, API version path changes.

Related errors


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