{"record":{"id":"8be2d84dba03bb27","repo":"jackwener/OpenCLI","slug":"label-returned-no-articles","errorCode":null,"errorMessage":"${label} returned no articles.","messagePattern":"(.+?) returned no articles\\.","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/juejin/utils.js","lineNumber":136,"sourceCode":"    }\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'err_no')) {\n        throw new CommandExecutionError(`${label} returned a malformed API envelope`);\n    }\n    if (payload.err_no !== 0) {\n        throw new CommandExecutionError(`${label} returned err_no ${payload.err_no}: ${payload.err_msg ?? ''}`);\n    }\n    return payload;\n}\n\nexport function readDataArray(payload, label) {\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'data')) {\n        throw new CommandExecutionError(`${label} returned a malformed payload`);\n    }\n    if (!Array.isArray(payload.data)) {\n        throw new CommandExecutionError(`${label} returned a non-array data field`);\n    }\n    if (payload.data.length === 0) {\n        throw new EmptyResultError(label, `${label} returned no articles.`);\n    }\n    return payload.data;\n}\n\nfunction readArticleId(value, label) {\n    const id = String(value ?? '').trim();\n    if (!JUEJIN_ID.test(id)) {\n        throw new CommandExecutionError(`${label} returned a malformed article id`);\n    }\n    return id;\n}\n\nfunction readOptionalNumber(value, label) {\n    if (value == null) return null;\n    const n = Number(value);\n    if (!Number.isFinite(n)) {\n        throw new CommandExecutionError(`${label} returned a malformed numeric field`);\n    }","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/juejin/utils.js#L118-L154","documentation":"readDataArray in clis/juejin/utils.js:136 throws an EmptyResultError when `payload.data` is a valid but empty array. This is a distinct, catchable signal meaning the query succeeded but Juejin returned zero articles — the library forces callers to handle the empty case explicitly rather than silently producing no output.","triggerScenarios":"Any successful request whose `data` array has length 0: an obscure category with no articles, a cursor past the last page of a feed, a time-window or filter that matches nothing, or a hot list queried at a moment with no entries.","commonSituations":"Paging a recommend feed past its final cursor; querying a niche category slug; filtering by a tag that has no current articles; running the command during a Juejin data hiccup where the list is temporarily empty.","solutions":["Treat it as a normal empty result: catch EmptyResultError and print a friendly 'no articles found' message.","If paginating, treat it as end-of-feed and stop requesting further cursors.","Broaden the query — use a major category alias (frontend, backend, ai) or remove restrictive filters.","Retry once after a short delay if emptiness is unexpected, to rule out a transient backend issue."],"exampleFix":"// before\nconst rows = readDataArray(payload, 'juejin recommend');\n// after\nlet rows;\ntry {\n    rows = readDataArray(payload, 'juejin recommend');\n} catch (err) {\n    if (err instanceof EmptyResultError) { console.log('No articles found.'); return; }\n    throw err;\n}","handlingStrategy":"try-catch","validationCode":"const data = payload?.data;\nif (Array.isArray(data) && data.length === 0) {\n  console.log('No articles found for this query.');\n  return [];\n}","typeGuard":"function hasArticles(p) {\n  return Array.isArray(p?.data) && p.data.length > 0;\n}","tryCatchPattern":"try {\n  const rows = readDataArray(payload, 'juejin recommend');\n  render(rows);\n} catch (err) {\n  if (err instanceof EmptyResultError) {\n    console.log('No articles found.');\n    return;\n  }\n  throw err;\n}","preventionTips":["Always handle EmptyResultError separately from CommandExecutionError — it is a normal outcome.","Stop paginating when you receive an empty page instead of requesting more cursors.","Prefer broad category aliases over niche ids when a non-empty listing matters.","Retry once on unexpectedly empty results to rule out transient backend gaps."],"tags":["empty-result","pagination","juejin"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}