mozilla/pdf.js · error · FormatError
Kid node must be a dictionary.
Error message
Kid node must be a dictionary.
What it means
Thrown inside getPageIndex's kid-counting loop after fetching a /Kids reference via xref.fetchAsync(kid). The resolved object is not a dictionary, but page and intermediate nodes must be dictionaries. This indicates a dangling or mispointed reference in the page tree.
Source
Thrown at src/core/catalog.js:1651
}
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")) {
const count = obj.get("Count");
if (Number.isInteger(count) && count >= 0) {
total += count;
return;
}
throw new FormatError("Count must be a (positive) integer.");
}
// Page leaf node.
total++;
})
);
}
if (!found) {
throw new FormatError("Kid reference not found in parent's kids.");
}
await Promise.all(kidPromises);View on GitHub (pinned to 5903d58d58)
Solutions
- Catch the rejection from getPageIndex and fall back to linear getPage iteration.
- Run the file through qpdf --fix or Ghostscript to rebuild the xref and page tree.
- If generated in-house, validate object graph integrity before writing the xref.
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
- Rebuild xref tables with qpdf --fix to repair dangling /Kids references.
- Validate object-graph integrity in your PDF generation pipeline.
- Keep a linear-scan fallback for documents with suspect xref tables.
When it happens
Trigger: A /Kids entry references an object that the xref resolves to a non-Dict (e.g., a stream, string, null, or number). The check runs inside `xref.fetchAsync(kid).then(obj => { if (!(obj instanceof Dict)) throw ... })`.
Common situations: Broken xref tables pointing /Kids entries at the wrong objects; PDFs with free or reused object numbers; files corrupted after generation; output from tools that write refs to non-page objects.
Related errors
- Parent must be a dictionary.
- Kids must be an array.
- Kid must be a reference.
- 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/f61a0d721293f7bb.
Report an issue: GitHub.