jackwener/OpenCLI · error · CommandExecutionError
${errorLabel} from Zhihu failed (HTTP ${status})
Error message
${errorLabel} from Zhihu failed (HTTP ${status}) What it means
fetchJson throws CommandExecutionError when a Zhihu API request fails with an HTTP status other than 401/403 (interpolated into the message) or with no response at all. It is the non-auth sibling of error 5137 within the same fetchJson helper.
Source
Thrown at clis/zhihu/collections.js:27
}
return n;
}
async function fetchJson(page, url, errorLabel) {
const data = await page.evaluate(`
(async () => {
const r = await fetch(${JSON.stringify(url)}, { credentials: 'include' });
if (!r.ok) return { __httpError: r.status };
return await r.json();
})()
`);
if (!data || data.__httpError) {
const status = data?.__httpError;
if (status === 401 || status === 403) {
throw new AuthRequiredError('www.zhihu.com', `${errorLabel} from Zhihu failed. Please ensure you are logged in.`);
}
throw new CommandExecutionError(
status ? `${errorLabel} from Zhihu failed (HTTP ${status})` : `${errorLabel} from Zhihu failed`,
'Try again later or rerun with -v for more detail',
);
}
return data;
}
function collectionKey(item) {
return String(item?.id || item?.url || item?.title || '');
}
cli({
site: 'zhihu',
name: 'collections',
access: 'read',
description: '知乎收藏夹列表(需要登录)',
domain: 'www.zhihu.com',
strategy: Strategy.COOKIE,View on GitHub (pinned to 49907e53dc)
Solutions
- Retry after a delay — most such failures are transient (429/5xx)
- Reduce call frequency / add backoff to avoid 429
- Update the CLI if Zhihu changed the API endpoint (404)
- Rerun with -v for detailed diagnostics
Example fix
// before
for (const u of urls) await fetchJson(page, u, 'list'); // hammers API -> 429
// after
for (const u of urls) { await fetchJson(page, u, 'list'); await sleep(1500); } Defensive patterns
Strategy: retry
Validate before calling
const res = await fetch('https://www.zhihu.com/api/v4/me', { headers: { 'x-zhihu-ping': '1' } });
if (!res.ok && res.status !== 401 && res.status !== 403) console.warn(`zhihu api health: ${res.status}`); Type guard
function isTransientHttpError(d) {
const s = d?.__httpError;
return typeof s === 'number' && (s === 429 || s >= 500);
} Try / catch
try {
return await fetchJson(page, url, label);
} catch (e) {
if (/HTTP (429|5\d\d)/.test(e.message) && attempt < 3) {
await sleep(1000 * 2 ** attempt);
return fetchJson(page, url, label);
}
throw e;
} Prevention
- Use exponential backoff on 429/5xx
- Space out bulk calls with delays
- Detect endpoint drift (404) and update the CLI
- Handle null data (network failure) with bounded retries
When it happens
Trigger: fetchJson receives __httpError with a status like 404, 429, or 5xx, or data is null (network failure, interrupted navigation) during any collections-listing API call.
Common situations: Zhihu rate limiting (429) after rapid successive calls; transient network drops; Zhihu server errors (5xx) during maintenance; an endpoint path changed after a Zhihu update.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Zhihu collection request failed (HTTP ${status})
- autohome ${contextHint} HTTP ${resp.status}
- Ctrip flight API returned HTTP ${status || 'unknown'}
- dongchedi ${contextHint} HTTP ${resp.status}
- eastmoney convertible failed: HTTP ${resp.status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/652df5d28b9d2dc7.
Report an issue: GitHub.