{"record":{"id":"aab82185d962fa4b","repo":"jackwener/OpenCLI","slug":"xiaoyuzhou-history","errorCode":null,"errorMessage":"xiaoyuzhou history","messagePattern":"xiaoyuzhou history","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/xiaoyuzhou/history.js","lineNumber":227,"sourceCode":"        if (!fetchAll && rows.length >= limit) break;\n        if (page.next === null) {\n            exhausted = true;\n            break;\n        }\n        if (page.next === loadMoreKey || seenCursors.has(page.next)) {\n            throw new CommandExecutionError('Xiaoyuzhou history pagination repeated the same cursor');\n        }\n        if (pageNumber === maxPages) {\n            throw new CommandExecutionError(\n                `Xiaoyuzhou history stopped at the --max-pages safety limit (${maxPages}) before reaching the end`,\n            );\n        }\n        seenCursors.add(page.next);\n        loadMoreKey = page.next;\n    }\n\n    if (rows.length === 0) {\n        throw new EmptyResultError('xiaoyuzhou history', 'The logged-in account has no playback history');\n    }\n    if (fetchAll && !exhausted) {\n        throw new CommandExecutionError('Xiaoyuzhou history archive did not reach the end of pagination');\n    }\n    return rows;\n}\n\ncli({\n    site: 'xiaoyuzhou',\n    name: 'history',\n    access: 'read',\n    description: 'List playback history for the logged-in Xiaoyuzhou account',\n    domain: 'api.xiaoyuzhoufm.com',\n    strategy: Strategy.LOCAL,\n    browser: false,\n    args: [\n        { name: 'limit', type: 'int', default: DEFAULT_LIMIT, help: `Maximum rows to return (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT}). Ignored with --all.` },\n        { name: 'all', type: 'bool', default: false, help: 'Fetch every history page until the API cursor is exhausted.' },","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaoyuzhou/history.js#L209-L245","documentation":"EmptyResultError for the 'xiaoyuzhou history' command: after pagination completed, zero history rows were collected. The library treats an empty history as an error rather than returning an empty list, so callers can distinguish 'no data' from a successful fetch.","triggerScenarios":"The logged-in account genuinely has no playback history; the history endpoint returns pages with zero entries; authentication succeeds but the account is new/reset; an API change moves entries to a different response field so parsing yields nothing.","commonSituations":"Freshly registered or wiped accounts; region/permission differences hiding history; API response shape changes silently emptying parsed entries; automated tests against empty accounts.","solutions":["Verify with a raw authenticated request that the history endpoint really returns no entries.","Check the account in the app/website to confirm history exists; if it does, inspect parsing against the current response shape.","Handle EmptyResultError explicitly in your code when an empty history is an acceptable outcome.","Re-authenticate if the credentials belong to an unexpected (new) account."],"exampleFix":"// before\nconst rows = await fetchHistory({ limit: 50 });\nconsole.log(rows);\n// after\nlet rows;\ntry { rows = await fetchHistory({ limit: 50 }); }\ncatch (e) {\n  if (e instanceof EmptyResultError) rows = [];\n  else throw e;\n}\nconsole.log(rows);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const rows = await fetchHistory(args);\n} catch (e) {\n  if (e instanceof EmptyResultError) {\n    return []; // empty history is acceptable here\n  }\n  throw e;\n}","preventionTips":["Catch EmptyResultError explicitly where empty history is expected (new accounts).","Verify the account has history via the website before debugging parsing.","Keep parsers updated against the current API response shape."],"tags":["empty-result","api","pagination","account-state"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}