jackwener/OpenCLI · error · CliError

NOT_FOUND

NOT_FOUND

Error message

No chapters found for this book

What it means

The ai-outline command in clis/weread/ai-outline.js throws CliError('NOT_FOUND') when the /book/chapterInfos API returns no chapters (chapterData?.data?.[0]?.updated is empty) for the given bookId. The library uses this to signal that the book ID is unusable rather than a network or auth problem.

Source

Thrown at clis/weread/ai-outline.js:99

    defaultFormat: 'plain',
    args: [
        { name: 'book-id', positional: true, required: true, help: 'Book ID (from shelf or search results)' },
        { name: 'limit', type: 'int', default: 200, help: 'Max outline items to return' },
        { name: 'depth', type: 'int', default: 4, help: 'Max outline depth (2=topics, 3=key points, 4=details)' },
        { name: 'raw', type: 'boolean', default: false, help: 'Output structured rows (chapter/idx/level/text) for programmatic use' },
    ],
    columns: undefined,
    func: async (page, args) => {
        const bookId = String(args['book-id'] || '').trim();
        const rawMode = Boolean(args.raw);

        const chapterData = await postWebApiWithCookies(page, '/book/chapterInfos', {
            bookIds: [bookId],
            sinces: [0],
        });
        const chapters = chapterData?.data?.[0]?.updated ?? [];
        if (chapters.length === 0) {
            throw new CliError('NOT_FOUND', 'No chapters found for this book', 'Check that the book ID is correct');
        }

        const chapterUids = chapters.map((c) => c.chapterUid);
        const chapterNameMap = new Map();
        for (const c of chapters) {
            chapterNameMap.set(c.chapterUid, c.title ?? '');
        }

        const outlineData = await postWebApi('/book/outline', {
            bookId,
            chapterUids,
        });

        const itemsArray = outlineData?.itemsArray ?? [];
        const maxDepth = Number(args.depth);
        const rawRows = [];

        for (const entry of itemsArray) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the book ID is correct — copy it again from the WeRead book page URL (weread.qq.com/web/reader/<id>) or from `weread shelf`/search output.
  2. Confirm the book is accessible in your logged-in WeRead account (some books are region/login restricted).
  3. Check chapterData by fetching the book page in a browser to confirm chapters exist.
  4. Try a different known-good bookId to rule out an account/session-specific empty response.

Example fix

// before
weread ai-outline 'wr_1234x'   // typo'd id -> NOT_FOUND
// after
weread ai-outline '3300027746' // correct id from book page URL
Defensive patterns

Strategy: validation

Validate before calling

const bookId = String(rawBookId || '').trim();
if (!bookId || !/^\d+$|^[A-Za-z0-9_-]+$/.test(bookId)) throw new Error(`Suspicious bookId: ${rawBookId}`);

Try / catch

try { await aiOutline(bookId); } catch (e) {
  if (e.code === 'NOT_FOUND') console.error(`Book ${bookId} has no chapters — verify the ID from the book page URL`);
  else throw e;
}

Prevention

When it happens

Trigger: Calling `ai-outline <book-id>` where POST /web/book/chapterInfos with {bookIds:[bookId], sinces:[0]} returns data[0].updated as an empty array or undefined — wrong/malformed bookId, a book with no chapter list, or restricted/foreign-region books.

Common situations: Passing a search-result ID from a different site, a truncated or quoted bookId, using an ID of a book that exists but whose chapter infos require entitlement, or a book that is unpublished/removed.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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