jackwener/OpenCLI · error · CommandExecutionError

${label} HTTP ${response.status}

Error message

${label} HTTP ${response.status}

What it means

After a successful fetch, eutilsFetch checks response.ok; a non-2xx status (429 rate limit, 5xx NCBI errors, 403) throws CommandExecutionError '<label> HTTP <status>' with a hint about NCBI availability, parameters, and the optional NCBI_API_KEY. Called by the xml, esearch, and result paths.

Source

Thrown at clis/pubmed/utils.js:106

    if (waitMs > 0) {
        await new Promise(resolve => setTimeout(resolve, waitMs));
    }
    lastRequestAt = Date.now();
}

export async function eutilsFetch(tool, params = {}, { retmode = 'json', label = 'PubMed E-utilities' } = {}) {
    const url = buildEutilsUrl(tool, { ...params, retmode });
    await waitForRateLimit();
    let response;
    try {
        response = await fetch(url);
    }
    catch (error) {
        const detail = error instanceof Error ? error.message : String(error);
        throw new CommandExecutionError(`${label} request failed`, detail);
    }
    if (!response.ok) {
        throw new CommandExecutionError(`${label} HTTP ${response.status}`, 'Check NCBI availability, request parameters, and optional NCBI_API_KEY.');
    }
    if (retmode === 'xml') {
        return response.text();
    }
    try {
        const json = await response.json();
        assertNoEutilsError(json, label);
        return json;
    }
    catch (error) {
        if (error instanceof CommandExecutionError) {
            throw error;
        }
        const detail = error instanceof Error ? error.message : String(error);
        throw new CommandExecutionError(`${label} returned invalid JSON`, detail);
    }
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Request a free NCBI_API_KEY and export it (raises the limit from 3 to 10 req/s)
  2. Add delays between sequential calls (e.g. sleep 400ms) to respect rate limits
  3. Retry with backoff on 429/5xx; check NCBI status on persistent 5xx
  4. Review request parameters if the status is 4xx

Example fix

// before
for (const q of queries) await pubmedSearch(q); // bursts >3 req/s
// after
export NCBI_API_KEY=your_key_here
for (const q of queries) {
  await pubmedSearch(q);
  await new Promise(r => setTimeout(r, 150));
}
Defensive patterns

Strategy: retry

Validate before calling

// space requests to stay under 3 req/s without an API key
await new Promise(r => setTimeout(r, 400)); // between calls
// and export NCBI_API_KEY=... to allow 10 req/s

Try / catch

async function withStatusRetry(fn, attempts = 3) {
  for (let i = 1; i <= attempts; i++) {
    try { return await fn(); }
    catch (err) {
      const m = /HTTP (\d+)/.exec(err.message ?? '');
      const status = m && Number(m[1]);
      if (status && (status === 429 || status >= 500) && i < attempts) {
        await new Promise(r => setTimeout(r, 2 ** i * 1000));
        continue;
      }
      throw err;
    }
  }
}

Prevention

When it happens

Trigger: Any pubmed command when NCBI returns 429 from exceeding 3 requests/second without an API key, 5xx during NCBI incidents, or 4xx from malformed eutils parameters.

Common situations: Burst-running many searches in a loop without an NCBI_API_KEY, NCBI maintenance windows, invalid tool/email parameters, blocked user agents.

Related errors


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