jackwener/OpenCLI · error · CommandExecutionError

WeRead in-book search returned non-advancing searchIdx

Error message

WeRead in-book search returned non-advancing searchIdx

What it means

searchWithinBook paginates by searchIdx: each page's last match must have a searchIdx strictly greater than the previous maxIdx. When the API returns a page whose last searchIdx <= maxIdx, the loop would fetch the same page forever, so the CLI throws CommandExecutionError instead.

Source

Thrown at clis/weread/book-search.js:313

            const snippet = normalizeSearchText(item.abstract);
            const searchIdx = parseOptionalFiniteNumber(item.searchIdx);
            if (!snippet || searchIdx == null || searchIdx <= 0) {
                throw new CommandExecutionError('WeRead in-book search returned malformed match');
            }
            return {
                ...item,
                abstract: snippet,
                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);
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Lower the limit so fewer pages are requested before the cursor misbehaves.
  2. Retry the search — re-ranking between pages is often transient.
  3. Add a page-count cap in your own wrapper and stop before the error.
  4. Report the cursor bug if it reproduces consistently for one book/query.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await searchWithinBook(bookId, query, { limit });
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('non-advancing searchIdx')) {
    return searchWithinBook(bookId, query, { limit: Math.min(limit, 50) }); // smaller limit, fewer pages
  }
  throw e;
}

Prevention

When it happens

Trigger: The in-book search endpoint returns a page whose final match's searchIdx does not advance past maxIdx — duplicated or re-sorted results, or a server bug after many pages.

Common situations: Deep pagination into large books where WeRead's index misbehaves; results re-ranked between requests; concurrent edits to the book shifting indices.

Related errors


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