jackwener/OpenCLI · error · CommandExecutionError
Zhihu answer download returned a malformed Browser Bridge pa
Error message
Zhihu answer download returned a malformed Browser Bridge payload
What it means
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.
Source
Thrown at clis/zhihu/download-helpers.js:205
return { value: {
answerUrl: typeof payload.url === 'string' ? payload.url : '',
questionUrl: typeof payload.question?.url === 'string' ? payload.question.url : '',
title: typeof payload.question?.title === 'string' ? payload.question.title : '',
author: typeof payload.author?.name === 'string' ? payload.author.name : '',
createdTime: payload.created_time,
...normalized
} };
})()
`).catch((error) => {
throw new CommandExecutionError(
`Zhihu answer download request failed: ${error instanceof Error ? error.message : String(error)}`,
'Try again later or rerun with -v for more detail.',
);
});
const data = unwrapEvaluateResult(raw);
if (!data || typeof data !== 'object' || Array.isArray(data)) {
throw new CommandExecutionError('Zhihu answer download returned a malformed Browser Bridge payload');
}
const status = data.status;
if (String(data.errorCode) === '40362') {
throw new CommandExecutionError(
`Zhihu risk control blocked answer ${target.answerId} (40362): ${data.errorMessage || 'abnormal request'}`,
'Open the answer in the connected Chrome profile and retry later.',
);
}
if (status === 401 || status === 403 || String(data.errorCode) === '40353' || data.needLogin) {
throw new AuthRequiredError('www.zhihu.com', 'Failed to download Zhihu answer');
}
if (status === 404) {
throw new EmptyResultError('zhihu download', `No Zhihu answer was found for ${target.answerId}.`);
}
if (status || data.fetchError) {
throw new CommandExecutionError(
status ? `Zhihu answer download request failed (HTTP ${status})` : 'Zhihu answer download request failed',
String(data.fetchError || data.errorMessage || 'Try again later or rerun with -v for more detail.'),View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before
const data = await extractAnswer(page, target); // may throw malformed-payload
// after
try {
const data = await extractAnswer(page, target);
} catch (err) {
if (/malformed Browser Bridge payload/.test(err.message)) {
console.error('Bridge returned unusable payload; update opencli + bridge and retry');
await bridge.restart();
return extractAnswer(page, target);
}
throw err;
} Defensive patterns
Strategy: type-guard
Validate before calling
// after a successful raw run, assert the bridge envelope shape yourself
function looksLikeBridgeEnvelope(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v);
}
const url = await page.getCurrentUrl();
if (!url || !url.includes('/answer/')) throw new Error('not on an answer page'); Type guard
function isBridgePayload(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v)
&& ('status' in v || 'value' in v || 'errorCode' in v || 'malformed' in v);
} Try / catch
try {
const data = await extractAnswer(page, target);
} catch (err) {
if (String(err.message).includes('malformed Browser Bridge payload')) {
// protocol/version mismatch or empty evaluate result — upgrade bridge, retry
await bridge.restart();
return extractAnswer(page, target);
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- Discord search returned malformed browser payload.
- ${command} returned an unreadable browser payload
- LinkedIn sent invitations returned a malformed extraction pa
- Reuters search API returned an unreadable response
- Failed to add @${username} to list ${listId}: malformed muta
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5e13dfaea9bc547a.
Report an issue: GitHub.