mozilla/pdf.js · error · Error

extractPages: sparse pageIndices.

Error message

extractPages: sparse pageIndices.

What it means

Plain Error thrown after collection if this.oldPages contains any undefined slot (a gap). Because reservePageSlot sets slots to null while collecting and then fills them with PageData, an undefined slot means pageIndices skipped an index (e.g., [0,2] leaves slot 1 undefined), producing a non-contiguous output document.

Source

Thrown at src/core/editor/pdf_editor.js:1103

        }
        reservePageSlot(newPageIndex);
        promises.push(
          document.getPage(i).then(page => {
            this.oldPages[newPageIndex] = new PageData(page, documentData);
          })
        );
      }
    }
    await Promise.all(promises);
    if (this.oldPages.length === 0) {
      throw new Error("extractPages: nothing to extract.");
    }
    const copyCounts = new Map();
    const documents = new Set();
    for (let i = 0, ii = this.oldPages.length; i < ii; i++) {
      const pageData = this.oldPages[i];
      if (pageData === undefined) {
        throw new Error("extractPages: sparse pageIndices.");
      }
      if (pageData) {
        const { page } = pageData;
        const copyLevel = copyCounts.get(page) ?? 0;
        copyCounts.set(page, copyLevel + 1);
        pageData.copyLevel = copyLevel;
        documents.add(pageData.documentData.document);
      }
    }
    this.isSingleFile = documents.size === 1;
    promises.length = 0;

    this.#collectValidDestinations(allDocumentData);
    this.#collectOutlineDestinations(allDocumentData);
    this.#collectPageLabels();

    for (const page of this.oldPages) {
      if (page) {

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Ensure pageIndices form a contiguous 0..N-1 range; fill any gap with another pageInfo or shift indices down.
  2. Use insertAfter for insertions rather than hand-picking sparse indices.
  3. After computing pageIndices, run a contiguity check: every integer in [0, max] must be present exactly once across all entries.

Example fix

// before
pageInfos = [{ document, pageIndices: [0, 2] }];   // slot 1 missing

// after
pageInfos = [{ document, pageIndices: [0, 1] }];
// or fill the gap:
pageInfos = [
  { document, pageIndices: [0] },
  { document: other, pageIndices: [1] },
  { document, pageIndices: [2] },
];
Defensive patterns

Strategy: validation

Validate before calling

function assertContiguous(pageInfos) {
  const all = pageInfos.flatMap(p => p.pageIndices ?? []).sort((a, b) => a - b);
  for (let i = 0; i < all.length; i++) {
    if (all[i] !== i) throw new Error(`pageIndices are not contiguous at position ${i} (got ${all[i]})`);
  }
}

Try / catch

try {
  await editor.extractPages(pageInfos, ...);
} catch (e) {
  if (e.message === 'extractPages: sparse pageIndices.') {
    pageInfos = compactPageIndices(pageInfos); // renumber to 0..N-1
    return editor.extractPages(pageInfos, ...);
  }
  throw e;
}

Prevention

When it happens

Trigger: pageIndices like [0, 2, 4]—skips 1 and 3; an insertAfter offset that leaves gaps; mixing auto-assigned and explicit indices incorrectly.

Common situations: Caller tries to insert pages at specific output positions but does not backfill the gaps with other content.

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/af4c975732d39cab. Report an issue: GitHub.