mozilla/pdf.js · error · FormatError
Kids must be an array.
Error message
Kids must be an array.
What it means
Thrown by Catalog.getPageIndex() after resolving a node's /Parent to a dictionary. That parent's /Kids entry is present but is not a PDF array. The spec mandates /Kids be an array of indirect references to child page or intermediate nodes, so a non-array value means the tree is structurally invalid.
Source
Thrown at src/core/catalog.js:1635
throw new FormatError("Pages tree contains circular reference.");
}
visited.put(parentRef);
}
const parent = await node.getAsync("Parent");
if (!parent) {
break;
}
if (!(parent instanceof Dict)) {
throw new FormatError("Parent must be a dictionary.");
}
const kids = await parent.getAsync("Kids");
if (!kids) {
break;
}
if (!Array.isArray(kids)) {
throw new FormatError("Kids must be an array.");
}
const kidPromises = [];
let found = false;
for (const kid of kids) {
if (!(kid instanceof Ref)) {
throw new FormatError("Kid must be a reference.");
}
if (isRefsEqual(kid, ref)) {
found = true;
break;
}
kidPromises.push(
xref.fetchAsync(kid).then(obj => {
if (!(obj instanceof Dict)) {
throw new FormatError("Kid node must be a dictionary.");
}
if (obj.has("Count")) {View on GitHub (pinned to 5903d58d58)
Solutions
- Fall back to a linear page scan (iterate pdfDocument.getPage(i)) wrapped in try-catch around getPageIndex.
- Rebuild the page tree with qpdf or Ghostscript to normalize /Kids into a proper array.
- Regenerate the PDF from the source document with a compliant producer.
Example fix
// before
const idx = await pdfDocument.getPageIndex(ref);
// after
let idx = -1;
try {
idx = await pdfDocument.getPageIndex(ref);
} catch (e) {
for (let i = 0; i < pdfDocument.numPages; i++) {
const p = await pdfDocument.getPage(i);
if (p.ref && p.ref.num === ref.num) { idx = i; break; }
}
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try {
idx = await pdfDocument.getPageIndex(ref);
} catch (e) {
for (let i = 0; i < pdfDocument.numPages; i++) {
const p = await pdfDocument.getPage(i);
if (p.ref && p.ref.num === ref.num) { idx = i; break; }
}
} Prevention
- Repair source PDFs with qpdf/Ghostscript to normalize /Kids arrays.
- When generating PDFs, always emit /Kids as an array of indirect references.
- Wrap getPageIndex in try-catch with a linear-scan fallback for untrusted inputs.
When it happens
Trigger: Calling getPageIndex on a PDF whose parent /Pages node has /Kids set to a single dictionary, a reference, a number, or any non-array object. The check is `Array.isArray(await parent.getAsync('Kids'))` returning false.
Common situations: Generators that emit a single child directly in /Kids instead of a one-element array; corrupt or partially rewritten page trees; PDFs merged incorrectly so /Kids arrays were flattened; spec-violating producers common in older office exporters.
Related errors
- Parent must be a dictionary.
- Kid must be a reference.
- Kid node must be a dictionary.
- Count must be a (positive) integer.
- Kid reference not found in parent's kids.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/1b123ccd9e03e8ab.
Report an issue: GitHub.