jackwener/OpenCLI · error · CommandExecutionError

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

Error message

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

What it means

This is the catch-all HTTP status branch of cratesFetch: any non-OK response that is not 404 or 429 becomes `"${label} returned HTTP ${resp.status}"` as a CommandExecutionError. It covers server errors (5xx), redirects the client won't follow, 403, and other unexpected statuses.

Source

Thrown at clis/crates/utils.js:62

        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 {
        body = await resp.json();
    }
    catch (err) {
        throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
    }
    return body;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the status code in the message: 5xx means server-side — wait and retry; 403 means blocked — check proxy/firewall.
  2. Check https://status.rust-lang.org for a crates.io outage before debugging locally.
  3. Test the same URL with `curl -i -H 'user-agent: ...'` to see whether the failure is client-side or service-side.
  4. Confirm you're on an up-to-date adapter version in case the crates.io endpoint changed.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const data = await opencli.crates.info(name);
} catch (err) {
  const m = err.message.match(/HTTP (\d{3})/);
  if (m && m[1] >= 500) {
    // transient server-side failure: retry later
  } else if (m && m[1] === 403) {
    // check proxy/firewall
  }
  throw err;
}

Prevention

When it happens

Trigger: Any crates subcommand calling cratesFetch when crates.io returns a non-OK status other than 404/429 — e.g. 500 during a backend incident, 403 from a firewall/CDN block, 502/503 from a proxy.

Common situations: crates.io or its CDN having an outage; corporate proxy intercepting TLS and returning 403; API version/endpoint change after an upgrade of the adapter.

Related errors


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