jackwener/OpenCLI · warning · EmptyResultError

No images found for illustration ${row.illust_id}.

Error message

No images found for illustration ${row.illust_id}.

What it means

After confirming the pages payload is an array, prepareIllustPlan checks that at least one page exists. If the array is empty — the illustration has no downloadable pages — the CLI throws EmptyResultError('pixiv bookmark-download', ...) so the caller can treat it as an expected 'nothing found' outcome rather than a crash. This is a deliberate, structured empty-result signal, distinct from the malformed-payload error.

Source

Thrown at clis/pixiv/bookmark-download.js:58

    throw new CommandExecutionError(`${label} returned a malformed image URL`);
  }
  const extension = path.extname(url.pathname).toLowerCase();
  const contentType = IMAGE_CONTENT_TYPES.get(extension);
  if (url.protocol !== 'https:' || url.hostname !== 'i.pximg.net' || url.username || url.password || url.port || !contentType) {
    throw new CommandExecutionError(`${label} returned an untrusted Pixiv image URL`);
  }
  return { url: url.href, extension, contentType };
}

async function prepareIllustPlan(page, row, outputRoot) {
  const pages = await pixivFetch(page, `/ajax/illust/${row.illust_id}/pages`, {
    notFoundMsg: `Illustration not found: ${row.illust_id}`,
  });
  if (!Array.isArray(pages)) {
    throw new CommandExecutionError('Pixiv pages API returned malformed payload');
  }
  if (pages.length === 0) {
    throw new EmptyResultError('pixiv bookmark-download', `No images found for illustration ${row.illust_id}.`);
  }
  const files = pages.map((entry, index) => {
    if (!entry || Array.isArray(entry) || typeof entry !== 'object' || !entry.urls || Array.isArray(entry.urls) || typeof entry.urls !== 'object') {
      throw new CommandExecutionError(`Pixiv illustration ${row.illust_id} returned malformed page ${index + 1}`);
    }
    const parsed = parsePixivImageUrl(entry.urls.original || entry.urls.regular, `Pixiv illustration ${row.illust_id} page ${index + 1}`);
    return {
      ...parsed,
      filename: `${row.illust_id}_p${index}${parsed.extension}`,
    };
  });
  const finalPath = path.join(outputRoot, 'illust', row.illust_id);
  if (pixivPathEntryExists(finalPath)) {
    throw new CommandExecutionError(`Refusing to overwrite existing Pixiv download: ${finalPath}`);
  }
  const createdDirs = [];
  for (let cursor = path.dirname(finalPath); !fs.existsSync(cursor); cursor = path.dirname(cursor)) {
    createdDirs.push(cursor);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the illust_id directly in a browser while logged in; if the work is deleted/private, remove it from the bookmark set and re-run
  2. Disable R-18 filtering / safe mode on the account whose session the CLI uses, since filtered works return empty page lists
  3. Confirm the id is an illustration id (numeric illust_id, not user/novel id)
  4. Re-authenticate with fresh cookies — restricted-session responses can come back as empty arrays
  5. Wrap this expected case: catch EmptyResultError and skip/log the illustration instead of failing the whole run

Example fix

// before
await bookmarkDownload({ illustId: row.illust_id });
// after
try {
  await bookmarkDownload({ illustId: row.illust_id });
} catch (err) {
  if (err instanceof EmptyResultError) { console.warn(`skipped ${row.illust_id}: no images`); return; }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that the work still exists and has pages before the run
const pages = await pixivFetch(page, `/ajax/illust/${row.illust_id}/pages`, {});
if (Array.isArray(pages) && pages.length === 0) console.warn(`illust ${row.illust_id} has no pages; skipping`);

Type guard

function hasPages(pages) {
  return Array.isArray(pages) && pages.length > 0;
}

Try / catch

try {
  await bookmarkDownload(row);
} catch (err) {
  if (err instanceof EmptyResultError) {
    console.warn(`${err.scope}: ${err.message} — skipping`); // expected outcome, not a failure
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: /ajax/illust/{illust_id}/pages returns [] — the illustration exists but exposes zero pages (e.g. works deleted/restricted after being bookmarked, R-18 works hidden by safe-mode/filter settings, or an id that resolves to an empty gallery).

Common situations: A bookmarked work was deleted or made private by the artist; Pixiv safe-search/filtering (R-18 filter) strips the page data; the wrong kind of id was passed (a user or novel id instead of an illust id) yielding an empty page list; regional or age-restricted content requiring different auth.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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