{"record":{"id":"5e13dfaea9bc547a","repo":"jackwener/OpenCLI","slug":"zhihu-answer-download-returned-a-malformed-browser","errorCode":null,"errorMessage":"Zhihu answer download returned a malformed Browser Bridge payload","messagePattern":"Zhihu answer download returned a malformed Browser Bridge payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/zhihu/download-helpers.js","lineNumber":205,"sourceCode":"        return { value: {\n          answerUrl: typeof payload.url === 'string' ? payload.url : '',\n          questionUrl: typeof payload.question?.url === 'string' ? payload.question.url : '',\n          title: typeof payload.question?.title === 'string' ? payload.question.title : '',\n          author: typeof payload.author?.name === 'string' ? payload.author.name : '',\n          createdTime: payload.created_time,\n          ...normalized\n        } };\n      })()\n    `).catch((error) => {\n        throw new CommandExecutionError(\n            `Zhihu answer download request failed: ${error instanceof Error ? error.message : String(error)}`,\n            'Try again later or rerun with -v for more detail.',\n        );\n    });\n\n    const data = unwrapEvaluateResult(raw);\n    if (!data || typeof data !== 'object' || Array.isArray(data)) {\n        throw new CommandExecutionError('Zhihu answer download returned a malformed Browser Bridge payload');\n    }\n    const status = data.status;\n    if (String(data.errorCode) === '40362') {\n        throw new CommandExecutionError(\n            `Zhihu risk control blocked answer ${target.answerId} (40362): ${data.errorMessage || 'abnormal request'}`,\n            'Open the answer in the connected Chrome profile and retry later.',\n        );\n    }\n    if (status === 401 || status === 403 || String(data.errorCode) === '40353' || data.needLogin) {\n        throw new AuthRequiredError('www.zhihu.com', 'Failed to download Zhihu answer');\n    }\n    if (status === 404) {\n        throw new EmptyResultError('zhihu download', `No Zhihu answer was found for ${target.answerId}.`);\n    }\n    if (status || data.fetchError) {\n        throw new CommandExecutionError(\n            status ? `Zhihu answer download request failed (HTTP ${status})` : 'Zhihu answer download request failed',\n            String(data.fetchError || data.errorMessage || 'Try again later or rerun with -v for more detail.'),","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/zhihu/download-helpers.js#L187-L223","documentation":"After the evaluate completes, extractAnswer unwraps the raw result with unwrapEvaluateResult and validates it is a non-null, non-array object before inspecting status/errorCode/value. If the unwrapped payload is not such an object, this error is thrown, meaning the Browser Bridge returned something the downloader could not interpret (null/undefined/array/primitive) rather than the expected {status, errorCode, value,...} envelope.","triggerScenarios":"Calling extractAnswer when page.evaluate resolves to a value that, after unwrapEvaluateResult, is not a plain object: the bridge returned null/undefined for a failed evaluation, an array, a bare string/number, or an unexpected wrapper shape due to a Browser Bridge protocol/version mismatch.","commonSituations":"Outdated or mismatched Browser Bridge/driver version serializing evaluate results differently; the evaluate returned undefined because the in-page script silently exited; the bridge's result-unwrapping convention changed between library versions; a corrupted or truncated bridge response.","solutions":["Update @jackwener/opencli and the Browser Bridge/driver to matching versions so evaluate results unwrap consistently.","Rerun with -v and log the raw evaluate result to inspect what shape actually came back.","Retry the command — a transient bridge glitch can yield an empty/null result.","If reproducible, check unwrapEvaluateResult/paginate.js for the expected envelope and confirm the connected bridge implements it."],"exampleFix":"// before\nconst data = await extractAnswer(page, target); // may throw malformed-payload\n// after\ntry {\n  const data = await extractAnswer(page, target);\n} catch (err) {\n  if (/malformed Browser Bridge payload/.test(err.message)) {\n    console.error('Bridge returned unusable payload; update opencli + bridge and retry');\n    await bridge.restart();\n    return extractAnswer(page, target);\n  }\n  throw err;\n}","handlingStrategy":"type-guard","validationCode":"// after a successful raw run, assert the bridge envelope shape yourself\nfunction looksLikeBridgeEnvelope(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\nconst url = await page.getCurrentUrl();\nif (!url || !url.includes('/answer/')) throw new Error('not on an answer page');","typeGuard":"function isBridgePayload(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v)\n    && ('status' in v || 'value' in v || 'errorCode' in v || 'malformed' in v);\n}","tryCatchPattern":"try {\n  const data = await extractAnswer(page, target);\n} catch (err) {\n  if (String(err.message).includes('malformed Browser Bridge payload')) {\n    // protocol/version mismatch or empty evaluate result — upgrade bridge, retry\n    await bridge.restart();\n    return extractAnswer(page, target);\n  }\n  throw err;\n}","preventionTips":["Keep @jackwener/opencli and the Browser Bridge at matching versions","Retry once on first occurrence — transient bridge glitches yield empty payloads","Log raw evaluate output with -v when diagnosing envelope-shape changes","Pin dependency versions in CI so bridge serialization behavior stays stable"],"tags":["payload","serialization","browser-automation","zhihu"],"backgroundTag":"malformed-response-payload","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}