jackwener/OpenCLI · error · CliError

PARSE_ERROR

PARSE_ERROR

Error message

Invalid JSON response for ${path}

What it means

After receiving the HTTP response, postWebApiWithCookies attempts resp.json(); if the body is not valid JSON (commonly an HTML login/error page or a gateway block page), it throws this CliError with code PARSE_ERROR naming the API path. WeRead returns HTML instead of JSON when it intercepts the request (login redirect, WAF/captcha, maintenance).

Source

Thrown at clis/weread/ai-outline.js:42

        headers: {
            'User-Agent': WEREAD_UA,
            'Content-Type': 'application/json',
            'Origin': WEREAD_WEB_ORIGIN,
            'Referer': `${WEREAD_WEB_ORIGIN}/`,
            ...(cookieHeader ? { 'Cookie': cookieHeader } : {}),
        },
        body: JSON.stringify(body),
    });

    if (resp.status === 401) {
        throw new CliError('AUTH_REQUIRED', 'Not logged in to WeRead', 'Please log in to weread.qq.com in Chrome first');
    }

    let data;
    try {
        data = await resp.json();
    } catch {
        throw new CliError('PARSE_ERROR', `Invalid JSON response for ${path}`, 'WeRead may have returned an HTML error page');
    }

    if (data?.errcode === -2010 || data?.errcode === -2012) {
        throw new CliError('AUTH_REQUIRED', 'Not logged in to WeRead', 'Please log in to weread.qq.com in Chrome first');
    }
    if (!resp.ok) {
        throw new CliError('FETCH_ERROR', `HTTP ${resp.status} for ${path}`, 'WeRead API may be temporarily unavailable');
    }
    return data;
}

async function postWebApi(path, body) {
    const url = `${WEB_API}${path}`;
    const resp = await fetch(url, {
        method: 'POST',
        headers: {
            'User-Agent': WEREAD_UA,
            'Content-Type': 'application/json',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-login to weread.qq.com in Chrome so requests stop being redirected to the HTML login page.
  2. Retry later if WeRead is rate limiting or under maintenance; reduce request frequency.
  3. Disable or bypass proxy/VPN interference that may inject HTML into responses.
  4. Inspect the raw response (curl the same endpoint with your cookies) to see what HTML is being returned.

Example fix

// before
const data = await postWebApiWithCookies('/book/chapter', body); // PARSE_ERROR on HTML page
// after: refresh session first, then retry with backoff
await refreshCookiesFromChrome();
const data = await retry(() => postWebApiWithCookies('/book/chapter', body), { retries: 2 });
Defensive patterns

Strategy: retry

Try / catch

const fetchJson = withRetry(async (path, body) => {
  try {
    return await postWebApiWithCookies(path, body);
  } catch (e) {
    if (e instanceof CliError && e.code === 'PARSE_ERROR') {
      if (attempts < 3) return null; // signal retry after backoff (session refresh first)
      throw e;
    }
    throw e;
  }
}, { retries: 3, backoffMs: 1000 });

Prevention

When it happens

Trigger: chapterData calling the web API and WeRead responding with an HTML page (login redirect, anti-bot challenge, rate-limit page) or a non-2xx empty body, so resp.json() rejects.

Common situations: Expired session causing a redirect to the login page; WeRead serving a captcha/security-check page; corporate proxy or VPN injecting HTML; server-side outage returning an error 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/13abe5b0b0d82c94. Report an issue: GitHub.