jackwener/OpenCLI · warning · EmptyResultError

weread book-search: No matches for "${query}" in book ${book

Error message

weread book-search: No matches for "${query}" in book ${bookId}

What it means

searchWithinBook completed pagination without collecting any valid match rows, so it throws EmptyResultError stating the query and bookId. This is a normal 'nothing found' outcome, not a protocol failure — the query simply has no matches in that book.

Source

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

            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),
            chapterTitle: normalizeSearchText(chapter?.title),
        });
    }
    return map;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the bookId corresponds to the intended book/edition.
  2. Try a shorter or alternate-language keyword.
  3. Search across all books (searchBookByQuery) instead of within one book.
  4. Handle EmptyResultError in your caller as a normal empty result, not a crash.

Example fix

// before
const rows = await matches(bookId, '机器学习');
// after
try {
  const rows = await matches(bookId, '机器学习');
} catch (e) {
  if (e instanceof EmptyResultError) return [];
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check impossible without searching; ensure inputs are sane:
if (!bookId || !/\d+/.test(bookId)) throw new Error('invalid bookId');
if (!query || !query.trim()) throw new Error('query required');

Try / catch

try {
  return await searchWithinBook(bookId, query);
} catch (e) {
  if (e instanceof EmptyResultError) {
    return []; // no matches is a normal outcome
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling searchWithinBook (via matches) with a query string that does not occur in the given book, or with mismatched bookId, or with a limit so small combined with filters that zero rows survive.

Common situations: Searching an English term in a Chinese book (or vice versa); typos; passing the wrong bookId after resolving the wrong book; expecting content that exists only in another edition.

Related errors


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