{"record":{"id":"0a47f901e5a30ccc","repo":"jackwener/OpenCLI","slug":"zhihu-label-returned-malformed-json-payload","errorCode":null,"errorMessage":"Zhihu ${label} returned malformed JSON: ${payload.__malformedJson}","messagePattern":"Zhihu (.+?) returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/zhihu/answer-comments-helpers.js","lineNumber":60,"sourceCode":"            return { __httpStatus: response.status, __malformedJson: error instanceof Error ? error.message : String(error) };\n        }\n        const error = body?.error && typeof body.error === 'object' ? body.error : null;\n        const result = {\n            __httpStatus: response.status,\n            __errorCode: error?.code ?? body?.error_code ?? '',\n            __errorMessage: error?.message || body?.error_msg || '',\n            __needLogin: error?.need_login === true || body?.need_login === true,\n        };\n        return !response.ok || result.__errorCode || result.__errorMessage || result.__needLogin ? result : body;\n    }, url).catch((error) => {\n        throw new CommandExecutionError(\n            `Zhihu ${label} request failed: ${error instanceof Error ? error.message : String(error)}`,\n            'Try again later or rerun with -v for more detail.',\n        );\n    });\n    const payload = unwrapEvaluateResult(evaluated);\n    if (payload?.__malformedJson) {\n        throw new CommandExecutionError(`Zhihu ${label} returned malformed JSON: ${payload.__malformedJson}`);\n    }\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n        throw new CommandExecutionError(`Zhihu ${label} returned a malformed payload`);\n    }\n    const status = payload.__httpStatus;\n    const code = String(payload.__errorCode || '');\n    if (status >= 400 || code || payload.__errorMessage || payload.__needLogin) {\n        if (code === '40362') {\n            throw new CommandExecutionError(\n                `Zhihu risk control blocked ${label} (40362): ${payload.__errorMessage || 'abnormal request'}`,\n                'Open the answer in the connected Chrome profile and retry later.',\n            );\n        }\n        if (status === 401 || status === 403 || code === '40353' || payload.__needLogin) {\n            throw new AuthRequiredError('www.zhihu.com', `Failed to fetch Zhihu ${label}`);\n        }\n        if (status === 404 && notFoundDetail) throw new EmptyResultError('zhihu answer-comments', notFoundDetail);\n        if (status >= 400) throw new CommandExecutionError(`Zhihu ${label} request failed (HTTP ${status})`);","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/zhihu/answer-comments-helpers.js#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rerun with -v to inspect the raw body captured in the malformed JSON detail","Open the answer URL in the connected Chrome profile, complete any login/captcha, then retry","Verify the answer URL/id is valid (the answer still exists and is public)","Retry later — transient risk-control HTML interstitials often clear after a cooldown"],"exampleFix":"// before\nconst payload = unwrapEvaluateResult(evaluated); // payload.__malformedJson set -> throw\n// after\n// handle gracefully at call site:\ntry { const p = await fetchCommentPage(...); } catch (e) { log(e.message); /* fall back to browser-visible fetch */ }","handlingStrategy":"try-catch","validationCode":"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);","typeGuard":"function isJsonPayload(p){ return !!p && typeof p === 'object' && !Array.isArray(p) && !p.__malformedJson; }","tryCatchPattern":"try { await fetchCommentPage(url); } catch (e) { if (String(e.message).includes('malformed JSON')) { /* open profile, complete login/captcha, retry */ } else throw e; }","preventionTips":["Send Accept: application/json on in-page fetches","Detect HTML responses early by checking content-type before JSON.parse","Keep the Chrome profile logged in to avoid login-page HTML","Throttle requests to avoid anti-bot HTML interstitials"],"tags":["zhihu","json-parse","network","scraping"],"backgroundTag":"malformed-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}