jackwener/OpenCLI · error · CommandExecutionError

weread-official ${apiName} returned invalid JSON

Error message

weread-official ${apiName} returned invalid JSON

What it means

response.json() failed, meaning the gateway returned a body that is not valid JSON (e.g. an HTML error page, empty body, or a proxy block page). callGateway converts this to CommandExecutionError with the parser's message as detail.

Source

Thrown at clis/weread-official/utils.js:117

    }
    finally {
        clearTimeout(timer);
    }

    if (!response.ok) {
        throw new CommandExecutionError(
            `weread-official ${apiName} HTTP ${response.status}`,
            'Check WeRead gateway availability and that WEREAD_API_KEY is still valid.',
        );
    }

    let payload;
    try {
        payload = await response.json();
    }
    catch (error) {
        const detail = error instanceof Error ? error.message : String(error);
        throw new CommandExecutionError(`weread-official ${apiName} returned invalid JSON`, detail);
    }

    if (payload && typeof payload === 'object' && payload.upgrade_info) {
        const info = payload.upgrade_info;
        const required = info?.required_version ?? info?.version ?? 'unknown';
        const message = info?.message ?? 'WeRead skill version is outdated';
        throw new CommandExecutionError(
            `WeRead skill 需升级: ${message}. Required skill_version=${required}, current=${SKILL_VERSION}`,
            'Pull the latest weread-skills.zip and bump SKILL_VERSION in clis/weread-official/utils.js.',
        );
    }

    const errcode = Number(payload?.errcode ?? 0);
    if (errcode !== 0) {
        const errmsg = String(payload?.errmsg ?? 'unknown error');
        if (AUTH_ERRCODES.has(errcode)) {
            throw new AuthRequiredError(
                WEREAD_DOMAIN,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Print the raw response body to see what was actually returned (likely HTML).
  2. Check for proxy/VPN interception and disable it or set NO_PROXY.
  3. Retry later if the gateway is serving a maintenance page.
  4. Verify the request is going to the correct gateway URL.
Defensive patterns

Strategy: try-catch

Validate before calling

const probe = await fetch(gatewayUrl, { method: 'HEAD' });
const ct = probe.headers.get('content-type') || '';
if (!ct.includes('json')) throw new Error(`Gateway returned ${ct || 'no content-type'} — likely HTML/proxy interception`);

Type guard

const isBadJson = (e) => e instanceof CommandExecutionError && /invalid JSON/.test(e.message);

Try / catch

try {
  return await callGateway(apiName, params);
} catch (e) {
  if (e instanceof CommandExecutionError && /invalid JSON/.test(e.message)) {
    console.error('Response was not JSON — check for proxy/VPN interception or gateway outage, then retry');
  }
  throw e;
}

Prevention

When it happens

Trigger: Gateway or an intermediary returning HTML (login page, 502 page, captcha challenge); truncated response; empty 200 response body; wrong content encoding.

Common situations: Captive portal or corporate proxy intercepting HTTPS; gateway outage serving an HTML maintenance page; hitting the wrong endpoint that returns a web page.

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/36ede38a9c8ef6fd. Report an issue: GitHub.