{"record":{"id":"98b20d1af007841f","repo":"mozilla/pdf.js","slug":"kid-must-be-a-reference","errorCode":null,"errorMessage":"Kid must be a reference.","messagePattern":"Kid must be a reference\\.","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/catalog.js","lineNumber":1642,"sourceCode":"        break;\n      }\n      if (!(parent instanceof Dict)) {\n        throw new FormatError(\"Parent must be a dictionary.\");\n      }\n\n      const kids = await parent.getAsync(\"Kids\");\n      if (!kids) {\n        break;\n      }\n      if (!Array.isArray(kids)) {\n        throw new FormatError(\"Kids must be an array.\");\n      }\n\n      const kidPromises = [];\n      let found = false;\n      for (const kid of kids) {\n        if (!(kid instanceof Ref)) {\n          throw new FormatError(\"Kid must be a reference.\");\n        }\n        if (isRefsEqual(kid, ref)) {\n          found = true;\n          break;\n        }\n        kidPromises.push(\n          xref.fetchAsync(kid).then(obj => {\n            if (!(obj instanceof Dict)) {\n              throw new FormatError(\"Kid node must be a dictionary.\");\n            }\n            if (obj.has(\"Count\")) {\n              const count = obj.get(\"Count\");\n              if (Number.isInteger(count) && count >= 0) {\n                total += count;\n                return;\n              }\n              throw new FormatError(\"Count must be a (positive) integer.\");\n            }","sourceCodeStart":1624,"sourceCodeEnd":1660,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/catalog.js#L1624-L1660","documentation":"Thrown by Catalog.getPageIndex() while iterating a parent's /Kids array. An element of that array is not an indirect object reference (Ref). The PDF spec requires /Kids to contain only indirect references; direct inline values violate the structure and cannot be counted.","triggerScenarios":"A parent /Pages node whose /Kids array contains a direct dictionary, number, string, or null instead of a Ref object. Triggered during the per-kid loop: `for (const kid of kids) { if (!(kid instanceof Ref)) throw ... }`.","commonSituations":"PDF authors who inline page dictionaries directly into /Kids rather than via indirect references; corrupt xref tables that turned references into direct objects; output from non-compliant converters.","solutions":["Catch the error from getPageIndex and fall back to a linear getPage scan.","Repair the file with Ghostscript or qpdf so all /Kids entries become indirect references.","Regenerate the PDF with a spec-compliant library."],"exampleFix":"// before\nconst pageIndex = await pdfDocument.getPageIndex(pageRef);\n\n// after\nlet pageIndex = -1;\ntry {\n  pageIndex = await pdfDocument.getPageIndex(pageRef);\n} catch (e) {\n  for (let i = 0; i < pdfDocument.numPages; i++) {\n    const page = await pdfDocument.getPage(i);\n    if (page.ref && page.ref.num === pageRef.num) { pageIndex = i; break; }\n  }\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  idx = await pdfDocument.getPageIndex(ref);\n} catch (e) {\n  for (let i = 0; i < pdfDocument.numPages; i++) {\n    const p = await pdfDocument.getPage(i);\n    if (p.ref && p.ref.num === ref.num) { idx = i; break; }\n  }\n}","preventionTips":["Ensure all /Kids entries are indirect references when authoring PDFs.","Run PDFs through Ghostscript to convert direct page dicts to indirect references.","Use a linear-scan fallback for untrusted or repaired PDFs."],"tags":["pdf","catalog","page-tree","corrupt-pdf","indirect-reference"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}