mozilla/pdf.js · error · FormatError
Page dictionary kids object is not an array.
Error message
Page dictionary kids object is not an array.
What it means
Thrown in Catalog.getPageDict() (catalog.js:1423) when a /Pages dictionary's /Kids entry is not an array, after the inline-Page recovery path (handling producers that inline Page dicts directly in Kids) also fails. /Kids must be an array of references; a non-array with a present /Kids that is not /Page-typed is invalid.
Source
Thrown at src/core/catalog.js:1423
kids = await xref.fetchAsync(kids);
}
if (!Array.isArray(kids)) {
// Prevent errors in corrupt PDF documents that violate the
// specification by *inlining* Page dicts directly in the Kids
// array, rather than using indirect objects (fixes issue9540.pdf).
let type = currentNode.getRaw("Type");
if (type instanceof Ref) {
type = await xref.fetchAsync(type);
}
if (isName(type, "Page") || !currentNode.has("Kids")) {
if (currentPageIndex === pageIndex) {
return [currentNode, null];
}
currentPageIndex++;
continue;
}
throw new FormatError("Page dictionary kids object is not an array.");
}
// Always check all `Kids` nodes, to avoid getting stuck in an empty
// node further down in the tree (see issue5644.pdf, issue8088.pdf),
// and to ensure that we actually find the correct `Page` dict.
for (let last = kids.length - 1; last >= 0; last--) {
const lastKid = kids[last];
nodesToVisit.push(lastKid);
// Launch all requests in parallel so we don't wait for each one in turn
// when looking for a page near the end, if all the pages are top level.
if (
currentNode === this.toplevelPagesDict &&
lastKid instanceof Ref &&
!pageDictCache.has(lastKid)
) {
pageDictCache.put(lastKid, xref.fetchAsync(lastKid));
}View on GitHub (pinned to 5903d58d58)
Solutions
- Repair with 'mutool clean' or 'qpdf --linearize' to normalise /Kids into an array of refs.
- Run 'qpdf --check' to detect the malformed /Kids before runtime.
- Enable recovery/ignoreErrors so PDF.js can skip the broken subtree.
- If producing PDFs, always emit /Kids as a PDF array of indirect references.
Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot cheaply validate /Kids shape pre-load via public API. // Repair: qpdf --linearize in.pdf out.pdf
Try / catch
try {
const page = await pdf.getPage(n);
} catch (err) {
if (/kids object is not an array/i.test(err?.message)) {
console.warn('/Kids is not an array; document needs repair', err);
} else throw err;
} Prevention
- Always write /Kids as a PDF array of indirect references when producing PDFs.
- Repair malformed trees with qpdf/mutool.
- Run 'qpdf --check' to catch the bad /Kids early.
- Use ignoreErrors/recovery for tolerant loading.
When it happens
Trigger: currentNode.getRaw('Kids') (after ref-fetch) is not an Array, and the node is not a /Page (isName(type,'Page') false) and still has a Kids key, so the recovery branch at line 1415 does not apply. Reached during getPage(n).
Common situations: A producer that wrote /Kids as a single dict or scalar instead of an array; a corrupt page tree where /Kids was overwritten; an edited PDF. Known-corrupt specimens are partially tolerated (issue9540.pdf) before this throws.
Related errors
- Pages tree contains circular reference.
- Page dictionary kid reference points to wrong type of object
- Page index ${pageIndex} not found.
- The reference does not point to a /Page dictionary.
- Node must be a dictionary.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/5240f085aff9771f.
Report an issue: GitHub.