jackwener/OpenCLI · error · CommandExecutionError

${label} returned malformed JSON: ${err?.message ?? err}

Error message

${label} returned malformed JSON: ${err?.message ?? err}

What it means

After a successful HTTP response, cratesFetch parses the body with resp.json(); if that throws, it raises `"${label} returned malformed JSON: ..."` as a CommandExecutionError. This means the endpoint responded with a 2xx but the payload was not valid JSON (or was truncated), so the response could be a proxy error page, HTML, or a partial body.

Source

Thrown at clis/crates/utils.js:69

    }
    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. Check what the endpoint actually returns: `curl -i <url>` and inspect the raw body for HTML/proxy text.
  2. Disable or bypass any intercepting proxy/VPN/captive portal and retry.
  3. Retry the command — truncation from transient network issues is common.
  4. If it persists on a specific endpoint, report it; the adapter may need to track a crates.io API format change.
Defensive patterns

Strategy: retry

Try / catch

try {
  const data = await opencli.crates.info(name);
} catch (err) {
  if (err.message.includes('malformed JSON')) {
    // bypass proxy / retry once after short delay
  }
  throw err;
}

Prevention

When it happens

Trigger: cratesFetch receives an OK response whose body fails JSON.parse: an intercepting proxy/captive portal returning HTML, a truncated response, or a changed endpoint returning a non-JSON format.

Common situations: Corporate proxies or antivirus rewriting responses; hotel/airport Wi-Fi captive portals; very large responses cut off by a middlebox; crates.io serving an HTML error page with 200.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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