{"record":{"id":"652df5d28b9d2dc7","repo":"jackwener/OpenCLI","slug":"errorlabel-from-zhihu-failed-http-status","errorCode":null,"errorMessage":"${errorLabel} from Zhihu failed (HTTP ${status})","messagePattern":"(.+?) from Zhihu failed \\(HTTP (.+?)\\)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/zhihu/collections.js","lineNumber":27,"sourceCode":"  }\n  return n;\n}\n\nasync function fetchJson(page, url, errorLabel) {\n  const data = await page.evaluate(`\n    (async () => {\n      const r = await fetch(${JSON.stringify(url)}, { credentials: 'include' });\n      if (!r.ok) return { __httpError: r.status };\n      return await r.json();\n    })()\n  `);\n\n  if (!data || data.__httpError) {\n    const status = data?.__httpError;\n    if (status === 401 || status === 403) {\n      throw new AuthRequiredError('www.zhihu.com', `${errorLabel} from Zhihu failed. Please ensure you are logged in.`);\n    }\n    throw new CommandExecutionError(\n      status ? `${errorLabel} from Zhihu failed (HTTP ${status})` : `${errorLabel} from Zhihu failed`,\n      'Try again later or rerun with -v for more detail',\n    );\n  }\n  return data;\n}\n\nfunction collectionKey(item) {\n  return String(item?.id || item?.url || item?.title || '');\n}\n\ncli({\n  site: 'zhihu',\n  name: 'collections',\n    access: 'read',\n  description: '知乎收藏夹列表（需要登录）',\n  domain: 'www.zhihu.com',\n  strategy: Strategy.COOKIE,","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/zhihu/collections.js#L9-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfor (const u of urls) await fetchJson(page, u, 'list');  // hammers API -> 429\n// after\nfor (const u of urls) { await fetchJson(page, u, 'list'); await sleep(1500); }","handlingStrategy":"retry","validationCode":"const res = await fetch('https://www.zhihu.com/api/v4/me', { headers: { 'x-zhihu-ping': '1' } });\nif (!res.ok && res.status !== 401 && res.status !== 403) console.warn(`zhihu api health: ${res.status}`);","typeGuard":"function isTransientHttpError(d) {\n  const s = d?.__httpError;\n  return typeof s === 'number' && (s === 429 || s >= 500);\n}","tryCatchPattern":"try {\n  return await fetchJson(page, url, label);\n} catch (e) {\n  if (/HTTP (429|5\\d\\d)/.test(e.message) && attempt < 3) {\n    await sleep(1000 * 2 ** attempt);\n    return fetchJson(page, url, label);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["http","network","rate-limit","zhihu"],"backgroundTag":"http-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}