jackwener/OpenCLI · error · CommandExecutionError
WeRead in-book search returned malformed pagination state
Error message
WeRead in-book search returned malformed pagination state
What it means
When a full page is returned but data.hasMore cannot be interpreted as true/false/1/0/'1'/'0', parseHasMore returns null. Since the page was full (length === pageSize) the loop would otherwise continue blindly; the CLI throws CommandExecutionError because it cannot determine whether more pages exist.
Source
Thrown at clis/weread/book-search.js:321
chapterIdx: parseOptionalFiniteNumber(item.chapterIdx),
chapterUid: parseOptionalFiniteNumber(item.chapterUid),
searchIdx,
};
});
if (result.length === 0)
break;
rows.push(...result);
const lastSearchIdx = result[result.length - 1].searchIdx;
if (lastSearchIdx <= maxIdx)
throw new CommandExecutionError('WeRead in-book search returned non-advancing searchIdx');
maxIdx = lastSearchIdx;
if (rows.length >= limit)
break;
const hasMore = parseHasMore(data?.hasMore);
if (hasMore == null) {
if (result.length < pageSize)
break;
throw new CommandExecutionError('WeRead in-book search returned malformed pagination state');
}
if (!hasMore)
break;
}
if (rows.length === 0) {
throw new EmptyResultError('weread book-search', `No matches for "${query}" in book ${bookId}`);
}
return rows.slice(0, limit);
}
function buildChapterMap(chapters) {
const map = new Map();
for (const chapter of chapters) {
const chapterUid = parseOptionalFiniteNumber(chapter?.chapterUid);
if (chapterUid == null)
continue;
map.set(chapterUid, {
chapterIdx: parseOptionalFiniteNumber(chapter?.chapterIdx),View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw response to see how hasMore is now represented and update parseHasMore.
- Reduce the query scope/limit so fewer full pages are fetched.
- Retry if the response was a transient degraded envelope (auth/rate limit).
Example fix
// before if (value === true || value === 1 || value === '1') return true; // after (accept 'true'/'false' strings) if (value === 'true' || value === true || value === 1 || value === '1') return true;
Defensive patterns
Strategy: try-catch
Type guard
function parseHasMoreSafe(v) {
if (v === true || v === 1 || v === '1' || v === 'true') return true;
if (v === false || v === 0 || v === '0' || v === 'false') return false;
return null;
} Try / catch
try {
return await searchWithinBook(bookId, query);
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('malformed pagination state')) {
return rowsSoFar; // accept what was collected
}
throw e;
} Prevention
- Reduce page pressure: smaller limits mean fewer full pages.
- Watch for hasMore representation changes in the WeRead API.
- Treat results already collected as usable when pagination is undecidable.
When it happens
Trigger: A full pageSize page arrives but data.hasMore is undefined, null, or an unexpected type (e.g. boolean-like string 'true', or the field renamed) — so pagination state is undecidable.
Common situations: WeRead API changing hasMore's representation (e.g. to 'true'/'false' strings or moving it into a nested object); error envelopes that keep result but drop hasMore.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- tieba search currently only supports --page ${MAX_SUPPORTED_
- WeRead book search result ${bookRank} is missing bookId
- WeRead in-book search returned malformed result
- WeRead in-book search returned malformed match
- WeRead in-book search returned non-advancing searchIdx
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/64bfda00f842e5ae.
Report an issue: GitHub.