jackwener/OpenCLI · critical · CommandExecutionError

${label} request failed: ${err?.message ?? err}

Error message

${label} request failed: ${err?.message ?? err}

What it means

cratesFetch wraps the underlying fetch to crates.io; if the request throws at the network layer (DNS failure, connection refused/reset, TLS error, offline), it rethrows as a CommandExecutionError with '<label> request failed: <cause>' and a hint to check reachability. It deliberately does not retry — transport errors surface immediately to the caller.

Source

Thrown at clis/crates/utils.js:47

    const raw = value ?? defaultValue;
    const n = typeof raw === 'number' ? raw : Number(raw);
    if (!Number.isInteger(n) || n <= 0) {
        throw new ArgumentError(`crates ${label} must be a positive integer`);
    }
    if (n > maxValue) {
        throw new ArgumentError(`crates ${label} must be <= ${maxValue}`);
    }
    return n;
}

export async function cratesFetch(url, label) {
    let resp;
    try {
        // crates.io requires a descriptive User-Agent per https://crates.io/data-access
        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
    }
    catch (err) {
        throw new CommandExecutionError(
            `${label} request failed: ${err?.message ?? err}`,
            'Check that crates.io is reachable from this network.',
        );
    }
    if (resp.status === 404) {
        throw new EmptyResultError(label, `crates.io returned 404 for ${url}.`);
    }
    if (resp.status === 429) {
        throw new CommandExecutionError(
            `${label} returned HTTP 429 (rate limited)`,
            'crates.io rate-limits unauthenticated traffic; wait a few seconds and retry.',
        );
    }
    if (!resp.ok) {
        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);
    }
    let body;
    try {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify network connectivity: curl -I https://crates.io/api/v1/crates/serde.
  2. Check proxy settings (HTTPS_PROXY/HTTP_PROXY) and corporate firewall rules; ensure fetch honors your proxy agent.
  3. Retry after a short backoff if the outage is transient; add your own retry wrapper around the call.
  4. Inspect the wrapped cause message (err?.message) for the specific socket/TLS error to target the fix.
  5. In CI, confirm the container has CA certificates and DNS resolution working.

Example fix

// before
const body = await cratesFetch(url, 'crates search'); // throws on first network blip
// after
const body = await withRetry(3, () => cratesFetch(url, 'crates search'));
// withRetry: attempts n times with exponential backoff, rethrowing the CommandExecutionError on final failure
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight reachability check before batch calls:
const ok = await fetch('https://crates.io/api/v1/summary', { method: 'HEAD' })
  .then(() => true)
  .catch(() => false);
if (!ok) throw new Error('crates.io unreachable — check network/proxy before running');

Type guard

function isNetworkCause(err) {
  const msg = String(err?.cause?.message ?? err?.message ?? '');
  return /ECONNREFUSED|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|CERT|fetch failed/i.test(msg);
}

Try / catch

async function fetchWithRetry(url, label, attempts = 3) {
  for (let i = 1; i <= attempts; i++) {
    try {
      return await cratesFetch(url, label);
    } catch (e) {
      const retriable = !(e instanceof EmptyResultError) && i < attempts;
      if (!retriable) throw e;
      await new Promise(r => setTimeout(r, 2 ** i * 500));
    }
  }
}

Prevention

When it happens

Trigger: Any crates.io call (`crates search`, `crates crate`) executed while offline, behind a blocking corporate proxy/firewall, with broken DNS, when crates.io is down, or in Node environments where fetch/HTTPS to crates.io is blocked (ECONNREFUSED, ENOTFOUND, CERT_HAS_EXPIRED, etc.).

Common situations: Working on a plane/VPN without internet, corporate proxies that block api crates.io traffic, IPv6 misconfiguration, expired local CA bundles in CI containers, or transient crates.io outages.

Related errors


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