jackwener/OpenCLI · error · CommandExecutionError
Zhihu answer detail returned malformed JSON: ${data.__malfor
Error message
Zhihu answer detail returned malformed JSON: ${data.__malformedJson} What it means
This CommandExecutionError is thrown when the in-page fetch succeeded but response.json() (or equivalent parsing) failed inside the evaluated script; the script returns { __malformedJson: <message> } and the command re-raises it as a command execution error. It means Zhihu returned a body that is not valid JSON — often an HTML error/challenge page instead of the API payload.
Source
Thrown at clis/zhihu/answer-detail.js:107
);
});
if (!data || data.__httpError) {
const status = data?.__httpError;
if (status === 401 || status === 403) {
throw new AuthRequiredError('www.zhihu.com', 'Failed to fetch Zhihu answer detail');
}
if (status === 404) {
throw new EmptyResultError('zhihu answer-detail', `No Zhihu answer was found for ${answerId}.`);
}
throw new CommandExecutionError(
status
? `Zhihu answer detail request failed (HTTP ${status})`
: 'Zhihu answer detail request failed',
'Try again later or rerun with -v for more detail',
);
}
if (data.__malformedJson) {
throw new CommandExecutionError(
`Zhihu answer detail returned malformed JSON: ${data.__malformedJson}`,
'Try again later or rerun with -v for more detail',
);
}
if (typeof data !== 'object' || Array.isArray(data)) {
throw new CommandExecutionError(
'Zhihu answer detail returned a malformed payload',
'Try again later or rerun with -v for more detail',
);
}
if (data.error || data.error_msg || data.message) {
throw new CommandExecutionError(
`Zhihu answer detail returned an error payload: ${data.error?.message || data.error_msg || data.message}`,
'Try again later or rerun with -v for more detail',
);
}
if (!Object.prototype.hasOwnProperty.call(data, 'content')) {
throw new CommandExecutionError(View on GitHub (pinned to 49907e53dc)
Solutions
- Retry later — transient challenge/HTML responses usually clear on a subsequent attempt.
- Open zhihu.com in the browser and complete any captcha/anti-bot challenge, then rerun.
- Rerun with -v for more detail; if persistent, re-login to refresh the session.
- Check for proxy/MITM software injecting HTML into responses.
Defensive patterns
Strategy: retry
Type guard
function isMalformedJsonError(err) { return /malformed JSON/.test(err?.message || ''); } Try / catch
try {
const detail = await answerDetail(id);
} catch (err) {
if (/malformed JSON/.test(err.message)) {
console.error('Non-JSON (likely anti-bot HTML) response — complete any captcha in the browser and retry.');
return retryWithBackoff(() => answerDetail(id), { attempts: 3, baseMs: 5000 });
}
throw err;
} Prevention
- Complete anti-bot challenges in the browser session before bulk runs.
- Slow request cadence — HTML challenge pages often follow aggressive scraping.
- Disable intercepting proxies/MITM tools that rewrite response bodies.
- Retry with backoff; challenge responses are frequently transient.
When it happens
Trigger: The evaluated script's JSON parse throws (caught and returned as data.__malformedJson): the response body was HTML (anti-bot challenge, login wall, error page) or an empty/truncated body.
Common situations: Zhihu's anti-crawler served a captcha/HTML page mid-session, a captive proxy rewrote the response, or the endpoint returned an empty 200 body under load.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Reuters search returned a non-JSON body${detail}
- toutiao recommend returned malformed JSON: ${error?.message
- Failed to parse 12306 station_name.js: source string not fou
- archive search returned malformed JSON: ${error?.message ||
- archive wayback returned malformed JSON: ${error?.message ||
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/dd0bc7d54a488800.
Report an issue: GitHub.