jackwener/OpenCLI · error · CommandExecutionError

Jike search API returned a malformed pagination cursor

Error message

Jike search API returned a malformed pagination cursor

What it means

After exhausting a page, searchPosts reads body.loadMoreKey as the pagination cursor. The Jike API contract expects an object; if it is a non-object (string, number) or an array, the CLI throws CommandExecutionError rather than sending a cursor it cannot serialize correctly. This protects against silently broken pagination.

Source

Thrown at clis/jike/search.js:60

    const seenCursors = new Set();
    let loadMoreKey = null;
    for (let pageIndex = 0; pageIndex < MAX_PAGES; pageIndex++) {
        const body = await fetchSearchPage(page, keyword, loadMoreKey);
        for (const item of body.data) {
            if (item?.type !== 'ORIGINAL_POST') continue;
            const row = mapPost(item);
            if (seenIds.has(row.id)) continue;
            seenIds.add(row.id);
            rows.push(row);
            if (rows.length >= limit) return rows;
        }
        const next = body.loadMoreKey;
        if (next == null) {
            if (rows.length === 0) throw new EmptyResultError('jike search', `No posts found for "${keyword}"`);
            return rows;
        }
        if (typeof next !== 'object' || Array.isArray(next)) {
            throw new CommandExecutionError('Jike search API returned a malformed pagination cursor');
        }
        const cursorKey = JSON.stringify(next);
        if (seenCursors.has(cursorKey)) {
            throw new CommandExecutionError('Jike search pagination returned a repeated cursor');
        }
        seenCursors.add(cursorKey);
        loadMoreKey = next;
    }
    throw new CommandExecutionError(`Jike search pagination exceeded ${MAX_PAGES} pages before satisfying --limit`);
}

cli({
    site: 'jike',
    name: 'search',
    access: 'read',
    description: '搜索即刻帖子',
    domain: 'web.okjike.com',
    strategy: Strategy.COOKIE,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the CLI/package to a version compatible with the current Jike API cursor format.
  2. Retry later — if Jike changed formats this is server-side, not client-fixable.
  3. Log the raw body.loadMoreKey value and inspect the actual type to confirm the schema change before patching locally.

Example fix

// before
if (typeof next !== 'object' || Array.isArray(next)) {
  throw new CommandExecutionError('Jike search API returned a malformed pagination cursor');
}
// after: accept string cursors too
const validCursor = next != null && (typeof next === 'object' || typeof next === 'string');
if (!validCursor) {
  throw new CommandExecutionError('Jike search API returned a malformed pagination cursor');
}
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: confirm the search endpoint responds normally on page 1 before deep paging
const first = await runCli(['jike', 'search', keyword, '--limit', '5']);

Type guard

const isCursor = (v) => v != null && typeof v === 'object' && !Array.isArray(v);

Try / catch

try {
  return await runCli(['jike', 'search', keyword, '--limit', n]);
} catch (e) {
  if (/malformed pagination cursor/.test(e.message)) return partialRows; // degrade gracefully
  throw e;
}

Prevention

When it happens

Trigger: The search response carries a loadMoreKey that is a string, number, boolean, or an Array instead of a plain object — e.g. Jike's API changed cursor format or returns an error marker in that field.

Common situations: Jike backend schema drift/rollback; requesting pagination with a logged-out or limited account whose responses differ; intermediate proxies rewriting response fields.

Understand the failure class

Related errors


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