{"record":{"id":"0effdda9d3fbd457","repo":"jackwener/OpenCLI","slug":"jike-search-pagination-returned-a-repeated-cursor","errorCode":null,"errorMessage":"Jike search pagination returned a repeated cursor","messagePattern":"Jike search pagination returned a repeated cursor","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/jike/search.js","lineNumber":64,"sourceCode":"        for (const item of body.data) {\n            if (item?.type !== 'ORIGINAL_POST') continue;\n            const row = mapPost(item);\n            if (seenIds.has(row.id)) continue;\n            seenIds.add(row.id);\n            rows.push(row);\n            if (rows.length >= limit) return rows;\n        }\n        const next = body.loadMoreKey;\n        if (next == null) {\n            if (rows.length === 0) throw new EmptyResultError('jike search', `No posts found for \"${keyword}\"`);\n            return rows;\n        }\n        if (typeof next !== 'object' || Array.isArray(next)) {\n            throw new CommandExecutionError('Jike search API returned a malformed pagination cursor');\n        }\n        const cursorKey = JSON.stringify(next);\n        if (seenCursors.has(cursorKey)) {\n            throw new CommandExecutionError('Jike search pagination returned a repeated cursor');\n        }\n        seenCursors.add(cursorKey);\n        loadMoreKey = next;\n    }\n    throw new CommandExecutionError(`Jike search pagination exceeded ${MAX_PAGES} pages before satisfying --limit`);\n}\n\ncli({\n    site: 'jike',\n    name: 'search',\n    access: 'read',\n    description: '搜索即刻帖子',\n    domain: 'web.okjike.com',\n    strategy: Strategy.COOKIE,\n    browser: true,\n    args: [\n        { name: 'query', type: 'string', required: true, positional: true, help: '即刻搜索关键词' },\n        { name: 'limit', type: 'int', default: DEFAULT_LIMIT },","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jike/search.js#L46-L82","documentation":"searchPosts tracks every pagination cursor it has seen (JSON-stringified). If the API returns a loadMoreKey identical to one already processed, pagination would loop forever, so the CLI throws CommandExecutionError to break the cycle. This indicates the Jike server is handing back the same page pointer.","triggerScenarios":"Two consecutive pages return the exact same loadMoreKey object, typically because the server-side cursor failed to advance while more results exist.","commonSituations":"Jike backend pagination bugs during high load; cursor not advancing for filtered/moderated keywords; stale session causing server to replay cached results.","solutions":["Reduce --limit so fewer pages are needed and retry.","Re-login / refresh the Jike session cookies and retry.","Wait and retry later — repeated cursors are usually a transient server-side issue.","Catch this error and return the rows collected so far instead of failing."],"exampleFix":"// before\nconst rows = await runCli(['jike', 'search', keyword, '--limit', '100']);\n// after: accept partial results\ntlet rows;\ntry { rows = await runCli(['jike', 'search', keyword, '--limit', '100']); }\ncatch (e) {\n  if (/repeated cursor/.test(e.message)) rows = [];\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"// keep --limit modest so pagination depth stays low\nconst LIMIT_MAX_SAFE = 100;\nconst limit = Math.min(requested, LIMIT_MAX_SAFE);","typeGuard":null,"tryCatchPattern":"let rows = [];\ntry {\n  rows = await runCli(['jike', 'search', keyword, '--limit', n]);\n} catch (e) {\n  if (/repeated cursor/.test(e.message)) console.warn('cursor loop at Jike; using partial results');\n  else throw e;\n}","preventionTips":["Retry after a delay — repeated cursors are often transient server-side.","Refresh session cookies before deep paging runs.","Cap --limit to reduce pagination depth and loop exposure.","Deduplicate by post id on your side so a retried run resumes safely."],"tags":["pagination","jike","api"],"backgroundTag":"pagination-cursor-loop","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}