jackwener/OpenCLI · error · CommandExecutionError

Zhihu ${label} returned malformed paging state

Error message

Zhihu ${label} returned malformed paging state

What it means

CommandExecutionError thrown when payload.paging exists but paging.is_end is not a boolean. The pagination loop relies on is_end to know when to stop fetching pages; without a definitive boolean it cannot terminate safely, so the library refuses to continue.

Source

Thrown at clis/zhihu/answer-comments-helpers.js:85

    if (status >= 400 || code || payload.__errorMessage || payload.__needLogin) {
        if (code === '40362') {
            throw new CommandExecutionError(
                `Zhihu risk control blocked ${label} (40362): ${payload.__errorMessage || 'abnormal request'}`,
                'Open the answer in the connected Chrome profile and retry later.',
            );
        }
        if (status === 401 || status === 403 || code === '40353' || payload.__needLogin) {
            throw new AuthRequiredError('www.zhihu.com', `Failed to fetch Zhihu ${label}`);
        }
        if (status === 404 && notFoundDetail) throw new EmptyResultError('zhihu answer-comments', notFoundDetail);
        if (status >= 400) throw new CommandExecutionError(`Zhihu ${label} request failed (HTTP ${status})`);
        throw new CommandExecutionError(`Zhihu ${label} returned an error payload: ${payload.__errorMessage || code}`);
    }
    if (!Array.isArray(payload.data) || !payload.paging || typeof payload.paging !== 'object') {
        throw new CommandExecutionError(`Zhihu ${label} returned a malformed payload`);
    }
    if (typeof payload.paging.is_end !== 'boolean') {
        throw new CommandExecutionError(`Zhihu ${label} returned malformed paging state`);
    }
    return payload;
}
function describeComment(comment, role, expectedRootId = '') {
    if (!comment || typeof comment !== 'object' || Array.isArray(comment)) {
        throw new CommandExecutionError(`Zhihu answer comments contained a malformed ${role} row`);
    }
    const id = commentId(comment.id);
    if (!id) throw new CommandExecutionError(`Zhihu answer comments contained a ${role} row without a stable id`);
    const rootId = role === 'root' ? id : commentId(comment.reply_root_comment_id);
    const parentId = role === 'root' ? '' : commentId(comment.reply_comment_id);
    if (role === 'child' && rootId !== expectedRootId) {
        throw new CommandExecutionError(`Zhihu answer comment ${id} had conflicting root provenance`);
    }
    if (role === 'child' && !parentId) {
        throw new CommandExecutionError(`Zhihu answer comment ${id} did not identify its immediate parent`);
    }
    const signature = JSON.stringify({

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect paging with -v to see what fields Zhihu now returns
  2. Coerce defensively: treat missing is_end as false only when next link is absent, otherwise stop after N pages as a safeguard
  3. Update the parser if Zhihu renamed/moved the field (e.g. paging.is_end -> another key)
  4. Add a max-page cap in your loop so any pagination anomaly terminates the fetch

Example fix

// before
while (!done) { const p = await fetchCommentPage(url); done = p.paging.is_end; } // throws on non-boolean
// after
let pages = 0;
while (!done && pages++ < 50) { const p = await fetchCommentPage(url); done = p.paging?.is_end === true || !p.paging?.next; }
Defensive patterns

Strategy: validation

Validate before calling

const body = await res.json(); if (typeof body?.paging?.is_end !== 'boolean') throw new Error('paging.is_end missing/non-boolean: ' + JSON.stringify(body?.paging));

Type guard

function hasValidPaging(p){ return typeof p?.paging?.is_end === 'boolean'; }

Try / catch

try { await fetchCommentPage(url); } catch (e) { if (/malformed paging/.test(e.message)) { /* stop paginating with a safe default or inspect paging keys */ } throw e; }

Prevention

When it happens

Trigger: The Zhihu comment response's paging object omitted is_end or typed it as something else (string 'true', number, undefined) — a schema deviation on the pagination metadata.

Common situations: Zhihu changing pagination metadata format; last-page responses omitting is_end; paginated endpoints for new content types behaving differently.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/533548625ca55f87. Report an issue: GitHub.