jackwener/OpenCLI · error · CommandExecutionError
Zhihu column extraction failed: ${error instanceof Error ? e
Error message
Zhihu column extraction failed: ${error instanceof Error ? error.message : String(error)} What it means
extractColumnArticle drives a connected Chrome page to zhuanlan.zhihu.com, waits 3 seconds, then runs an in-page evaluate script that scrapes title/author/publishTime and normalizes content images. If that evaluate call rejects (script error, page closed, navigation interrupted, selector crash), the promise's .catch rethrows it as a CommandExecutionError with the underlying message appended. It is a wrapper error: the real cause is in the appended message.
Source
Thrown at clis/zhihu/download-helpers.js:140
}
export async function extractColumnArticle(page, target) {
await page.goto(target.url);
await page.wait(3);
const normalize = `(${normalizeContentImages.toString()})`;
const raw = await page.evaluate(`
(() => {
const content = document.querySelector('.Post-RichTextContainer, .RichText, .ArticleContent');
const normalized = ${normalize}(content?.innerHTML || '');
return {
title: document.querySelector('.Post-Title, h1.ContentItem-title, .ArticleTitle')?.textContent?.trim() || 'untitled',
author: document.querySelector('.AuthorInfo-name, .UserLink-link')?.textContent?.trim() || '',
publishTime: document.querySelector('.ContentItem-time, .Post-Time')?.textContent?.trim() || '',
...normalized
};
})()
`).catch((error) => {
throw new CommandExecutionError(`Zhihu column extraction failed: ${error instanceof Error ? error.message : String(error)}`);
});
return requireArticle(raw);
}
export async function extractAnswer(page, target) {
try {
await page.goto(`https://www.zhihu.com/answer/${target.answerId}`);
}
catch (error) {
throw new CommandExecutionError(
`Failed to open Zhihu answer ${target.answerId}: ${error instanceof Error ? error.message : String(error)}`,
'Open the answer URL in Chrome and retry after the page is reachable.',
);
}
const currentUrl = typeof page.getCurrentUrl === 'function' ? await page.getCurrentUrl().catch(() => '') : '';
const currentTarget = parseAnswerTarget(currentUrl);
if (!currentTarget || currentTarget.answerId !== target.answerId || !currentTarget.questionId
|| (target.questionId && currentTarget.questionId && target.questionId !== currentTarget.questionId)) {View on GitHub (pinned to 49907e53dc)
Solutions
- Read the appended underlying message; if the tab/page was lost, reconnect the Browser Bridge and rerun the download command.
- Open the article URL (https://zhuanlan.zhihu.com/p/<id>) in the connected Chrome profile to confirm it loads and is not behind a login/captcha wall.
- Increase tolerance for slow loads: rerun on a stable connection or retry, since transient redirects during page.wait(3) cause this.
- Verify the article id/target is valid via parseDownloadTarget before calling; a bad target leads to Zhihu error pages.
Example fix
// before
const raw = await extractColumnArticle(page, { kind: 'article', articleId, url });
// after
let raw;
try {
raw = await extractColumnArticle(page, { kind: 'article', articleId, url });
} catch (err) {
console.error('Column extraction failed:', err.message, '- reconnect Chrome and retry');
await bridge.reconnect();
raw = await extractColumnArticle(page, { kind: 'article', articleId, url });
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!target || target.kind !== 'article' || !/^\d+$/.test(target.articleId)) {
throw new Error('invalid article target before extraction');
}
// ensure the bridge page is alive
await page.goto(target.url); // surface navigation errors early, outside the library Type guard
function isArticleTarget(t) {
return !!t && typeof t === 'object' && t.kind === 'article'
&& typeof t.articleId === 'string' && /^\d+$/.test(t.articleId)
&& typeof t.url === 'string';
} Try / catch
try {
const article = await extractColumnArticle(page, target);
} catch (err) {
if (String(err.message).includes('Zhihu column extraction failed')) {
// underlying cause follows the colon — log it, reconnect, retry once
await reconnectBridge();
return extractColumnArticle(page, target);
}
throw err;
} Prevention
- Keep the Chrome tab controlled by the bridge open and in the foreground during downloads
- Log in to Zhihu in the connected profile to avoid login-wall redirects mid-scrape
- Validate targets with parseDownloadTarget before calling extraction functions
- Wrap extraction calls in a retry with backoff for transient navigation errors
When it happens
Trigger: Calling extractColumnArticle(page, target) when page.evaluate throws: the Browser Bridge tab was closed mid-scrape, the page navigated away or redirected (e.g. to a login/captcha wall) before the script ran, the in-page IIFE threw, or the bridge connection dropped during the 3s wait.
Common situations: Chrome was quit or the tab closed while the CLI ran; Zhihu redirected the column URL to an error/login page; slow network meant the DOM was torn down by a redirect during page.wait(3); an expired login session triggered a redirect the bridge surfaced as a navigation error.
Related errors
- Failed to open Zhihu answer ${answerId}: ${err instanceof Er
- Failed to fetch Barchart greeks for ${symbol}
- Failed to load Booking.com search page: ${err?.message || er
- Failed to extract Booking.com cards: ${err?.message || err}
- Booking.com page returned no extractable data
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/01a66912bb003a8d.
Report an issue: GitHub.