jackwener/OpenCLI · error · CommandExecutionError

Zhihu ${label} returned malformed JSON: ${payload.__malforme

Error message

Zhihu ${label} returned malformed JSON: ${payload.__malformedJson}

What it means

This CommandExecutionError is thrown by fetchCommentPage when the in-browser fetch of a Zhihu comment endpoint returned a payload flagged with __malformedJson, meaning the HTTP body could not be parsed as JSON inside the page context. The library throws it early so the malformed raw text can be surfaced instead of crashing later on undefined fields. It wraps the parse error message from the evaluated fetch helper.

Source

Thrown at clis/zhihu/answer-comments-helpers.js:60

            return { __httpStatus: response.status, __malformedJson: error instanceof Error ? error.message : String(error) };
        }
        const error = body?.error && typeof body.error === 'object' ? body.error : null;
        const result = {
            __httpStatus: response.status,
            __errorCode: error?.code ?? body?.error_code ?? '',
            __errorMessage: error?.message || body?.error_msg || '',
            __needLogin: error?.need_login === true || body?.need_login === true,
        };
        return !response.ok || result.__errorCode || result.__errorMessage || result.__needLogin ? result : body;
    }, url).catch((error) => {
        throw new CommandExecutionError(
            `Zhihu ${label} request failed: ${error instanceof Error ? error.message : String(error)}`,
            'Try again later or rerun with -v for more detail.',
        );
    });
    const payload = unwrapEvaluateResult(evaluated);
    if (payload?.__malformedJson) {
        throw new CommandExecutionError(`Zhihu ${label} returned malformed JSON: ${payload.__malformedJson}`);
    }
    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
        throw new CommandExecutionError(`Zhihu ${label} returned a malformed payload`);
    }
    const status = payload.__httpStatus;
    const code = String(payload.__errorCode || '');
    if (status >= 400 || code || payload.__errorMessage || payload.__needLogin) {
        if (code === '40362') {
            throw new CommandExecutionError(
                `Zhihu risk control blocked ${label} (40362): ${payload.__errorMessage || 'abnormal request'}`,
                'Open the answer in the connected Chrome profile and retry later.',
            );
        }
        if (status === 401 || status === 403 || code === '40353' || payload.__needLogin) {
            throw new AuthRequiredError('www.zhihu.com', `Failed to fetch Zhihu ${label}`);
        }
        if (status === 404 && notFoundDetail) throw new EmptyResultError('zhihu answer-comments', notFoundDetail);
        if (status >= 400) throw new CommandExecutionError(`Zhihu ${label} request failed (HTTP ${status})`);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Rerun with -v to inspect the raw body captured in the malformed JSON detail
  2. Open the answer URL in the connected Chrome profile, complete any login/captcha, then retry
  3. Verify the answer URL/id is valid (the answer still exists and is public)
  4. Retry later — transient risk-control HTML interstitials often clear after a cooldown

Example fix

// before
const payload = unwrapEvaluateResult(evaluated); // payload.__malformedJson set -> throw
// after
// handle gracefully at call site:
try { const p = await fetchCommentPage(...); } catch (e) { log(e.message); /* fall back to browser-visible fetch */ }
Defensive patterns

Strategy: try-catch

Validate before calling

const res = await fetch(url, {headers:{accept:'application/json'}}); const ct = res.headers.get('content-type')||''; if (!ct.includes('json')) throw new Error('non-JSON response: ' + ct);

Type guard

function isJsonPayload(p){ return !!p && typeof p === 'object' && !Array.isArray(p) && !p.__malformedJson; }

Try / catch

try { await fetchCommentPage(url); } catch (e) { if (String(e.message).includes('malformed JSON')) { /* open profile, complete login/captcha, retry */ } else throw e; }

Prevention

When it happens

Trigger: The browser evaluate returned an object whose __malformedJson property is set — i.e. Zhihu's endpoint responded with HTML (login page, anti-bot interstitial), an empty body, or invalid JSON instead of the expected JSON API response.

Common situations: Zhihu serving an HTML login/verification page instead of JSON; rate limiting returning an HTML block page; the answer URL being wrong so an HTML 404 page is returned; network middleware/proxy injecting HTML error pages.

Understand the failure class

Related errors


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