jackwener/OpenCLI · error · CommandExecutionError

${label} returned HTTP ${resp.status}.

Error message

${label} returned HTTP ${resp.status}.

What it means

For any HTTP status that is not 404 or 429 and not ok, openfdaFetch throws this CommandExecutionError reporting the raw status code. It is the catch-all for server-side or authorization problems at api.fda.gov that are neither 'no matches' nor throttling. The label names the originating command.

Source

Thrown at clis/openfda/utils.js:41

    return n;
}

export async function openfdaFetch(url, label) {
    let resp;
    try {
        resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });
    } catch (err) {
        throw new CommandExecutionError(`${label} request failed: ${err.message}`);
    }
    if (resp.status === 404) {
        // openFDA returns 404 for "no matches" instead of an empty results array.
        throw new EmptyResultError(label, `${label} returned 404 (no matches).`);
    }
    if (resp.status === 429) {
        throw new CommandExecutionError(`${label} rate-limited (HTTP 429); back off and retry.`);
    }
    if (!resp.ok) {
        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}.`);
    }
    let body;
    try {
        body = await resp.json();
    } catch (err) {
        throw new CommandExecutionError(`${label} returned non-JSON body: ${err.message}`);
    }
    return body;
}

// openFDA returns most string fields as `[string]` arrays — collapse to first
// element. Preserves `null` (not coerced to empty string) when the slot is
// missing entirely.
export function firstOrNull(arr) {
    if (!Array.isArray(arr) || !arr.length) return null;
    const v = arr[0];
    if (typeof v !== 'string') return v ?? null;
    const trimmed = v.trim();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the status: 5xx means retry later with backoff; 401/403 means fix the API key; 400 means fix the query syntax.
  2. Check the openFDA status page / open.fda.gov to see if the API is degraded.
  3. Validate and simplify the search query (fewer clauses, proper +AND+ / +OR+ encoding).
  4. Include any configured API key correctly in the request and confirm it is still valid.

Example fix

// before
await openfdaFetch(`${OPENFDA_BASE}/drug/label.json?search=${rawQuery}`, 'openfda drug-label'); // 500 risk
// after
try {
  await openfdaFetch(`${OPENFDA_BASE}/drug/label.json?search=${encodeURIComponent(rawQuery)}`, 'openfda drug-label');
} catch (e) {
  await new Promise(r => setTimeout(r, 5000)); // retry on transient 5xx
  return openfdaFetch(url, 'openfda drug-label');
}
Defensive patterns

Strategy: try-catch

Validate before calling

function buildSearchQuery(clauses) {
  if (!Array.isArray(clauses) || clauses.length === 0) throw new Error('at least one search clause required');
  return clauses.map(encodeURIComponent).join('+AND+');
}

Type guard

function isServerError(e) {
  const m = e?.message?.match(/returned HTTP (\d{3})\./);
  return m != null && Number(m[1]) >= 500;
}

Try / catch

try {
  const body = await openfdaFetch(url, label);
} catch (e) {
  const m = e.message.match(/returned HTTP (\d{3})\./);
  const code = m && Number(m[1]);
  if (code >= 500) { /* backoff + retry */ }
  else if (code === 401 || code === 403) { /* fix API key */ }
  else if (code === 400) { /* fix query syntax */ }
  else throw e;
}

Prevention

When it happens

Trigger: HTTP 500/502/503 when openFDA is down or a backend error occurs; HTTP 401/403 when an invalid API key is supplied or traffic is blocked; HTTP 400 from a malformed query that slips past client validation.

Common situations: openFDA maintenance windows returning 503; an expired or mistyped API key yielding 403; an over-complex search string the API rejects with 400; a load balancer 502 during traffic spikes.

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 jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/27e4712e004317d2. Report an issue: GitHub.