{"record":{"id":"6856271687a846fe","repo":"jackwener/OpenCLI","slug":"zhihu-search-pagination-returned-a-repeated-next-u","errorCode":null,"errorMessage":"Zhihu search pagination returned a repeated next URL","messagePattern":"Zhihu search pagination returned a repeated next URL","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/zhihu/search.js","lineNumber":179,"sourceCode":"            for (const item of data.data) {\n                const rawType = item?.object?.type;\n                if (type !== 'all' && rawType && rawType !== type) continue;\n                const normalized = normalizeResultItem(item);\n                if (!normalized) continue;\n                if (type !== 'all' && normalized.row.type !== type) continue;\n                if (seen.has(normalized.key)) continue;\n                seen.add(normalized.key);\n                results.push(normalized.row);\n                if (results.length >= resultLimit) break;\n            }\n            if (results.length >= resultLimit) break;\n            if (data.paging?.is_end) break;\n            const next = normalizeSearchUrl(data.paging?.next);\n            if (!next) {\n                throw new CommandExecutionError('Zhihu search pagination returned malformed next URL');\n            }\n            if (visited.has(next)) {\n                throw new CommandExecutionError('Zhihu search pagination returned a repeated next URL');\n            }\n            url = next;\n        }\n        if (results.length === 0) {\n            throw new EmptyResultError('zhihu search', `No ${type === 'all' ? '' : `${type} `}results found for \"${query}\"`);\n        }\n        return results.map((row, i) => {\n            return {\n                rank: i + 1,\n                ...row,\n            };\n        });\n    },\n});\n\nexport const __test__ = {\n    stripHtml,\n    itemKey,","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/zhihu/search.js#L161-L197","documentation":"The search pager tracks every followed next URL in a `visited` set. If Zhihu's API returns a paging.next URL that was already followed, the CLI throws to prevent an infinite pagination loop (repeatedly fetching the same page). This detects buggy or wrapped pagination responses.","triggerScenarios":"paging.next points back to a previously fetched page (same normalized URL), e.g. the API ignores the offset/cursor parameter, or a proxy strips query parameters so every next link normalizes to the same URL.","commonSituations":"Caching layer or corporate proxy serving stale pages, Zhihu cursor parameter ignored under rate limiting, normalizeSearchUrl stripping a distinguishing query param after a change in the URL format.","solutions":["Re-run the search to rule out transient cache/proxy staleness","Check whether a proxy/cache is stripping cursor or offset query parameters","Update normalizeSearchUrl so it preserves pagination parameters","Lower resultLimit to end pagination before the loop point"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const seen = new Set();\nlet probe = data.paging?.next && new URL(data.paging.next);\nif (probe && seen.has(probe.href)) throw new Error('pagination would loop');\nseen.add(probe.href);","typeGuard":"function isFreshNext(next, visited) {\n  return typeof next === 'string' && !visited.has(next);\n}","tryCatchPattern":"try {\n  const results = await zhihuSearch(query, opts);\n} catch (err) {\n  if (err.message.includes('repeated next URL')) {\n    console.error('Zhihu pagination is looping (cache/proxy stripping cursor params); dedupe results manually');\n  } else throw err;\n}","preventionTips":["Ensure proxies/caches do not strip cursor or offset query parameters","Keep normalizeSearchUrl from discarding distinguishing pagination params","Dedupe by item key, not only by URL, when merging pages","Set a hard max-page bound as a loop backstop"],"tags":["zhihu","search","pagination","infinite-loop"],"backgroundTag":"pagination-loop-detected","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}