mozilla/pdf.js · critical · FormatError
Catalog object is not a dictionary.
Error message
Catalog object is not a dictionary.
What it means
Thrown in the Catalog constructor (catalog.js:157) when the root/catalog object returned by xref.getCatalogObj() is not a PDF Dict. The catalog is the document's top-level dictionary (/Root); if it is anything else (null, stream, array, number), the PDF is structurally invalid and cannot be processed at all.
Source
Thrown at src/core/catalog.js:157
nonBlendModesSet = new RefSet();
pageDictCache = new RefMap();
pageIndexCache = new RefMap();
pageKidsCountCache = new RefMap();
standardFontDataCache = new Map();
systemFontCache = new Map();
constructor(pdfManager, xref) {
this.pdfManager = pdfManager;
this.xref = xref;
this.#catDict = xref.getCatalogObj();
if (!(this.#catDict instanceof Dict)) {
throw new FormatError("Catalog object is not a dictionary.");
}
// Given that `XRef.parse` will both fetch *and* validate the /Pages-entry,
// the following call must always succeed here:
this.toplevelPagesDict; // eslint-disable-line no-unused-expressions
}
cloneDict() {
return this.#catDict.clone();
}
/**
* Create an id for an attachment from a FileAttachment annotation.
*
* The id is registered here rather than parsed from a public string prefix in
* `attachmentContent`, since catalog attachment names can be arbitrary PDF
* strings and may otherwise collide with annotation-local ids.
*
* @param {Ref} refView on GitHub (pinned to 5903d58d58)
Solutions
- Re-acquire the PDF from a trusted source and confirm it opens in Adobe Acrobat or another strict reader.
- Run a structural check: 'qpdf --check file.pdf' or 'mutool info file.pdf' to inspect the trailer and /Root.
- Repair the xref/catalog with 'qpdf --linearize' or 'mutool clean' and load the repaired output.
- Verify the byte stream passed to getDocument() is the complete file (check size/checksum against the source).
Example fix
// before: passing a possibly-truncated/corrupt blob unchecked
const task = getDocument({ data: arrayBuffer });
// after: guard with a quick structural sanity check + repair fallback
function looksLikePdf(buf) {
const head = new TextDecoder().decode(buf.slice(0, 5));
return head === '%PDF-';
}
if (!looksLikePdf(arrayBuffer)) throw new Error('not a PDF');
try {
await getDocument({ data: arrayBuffer }).promise;
} catch (e) {
// route the user to a server-side repair (qpdf/ghostscript) then retry
} Defensive patterns
Strategy: try-catch
Validate before calling
// Best-effort pre-check: confirm the bytes look like a PDF before loading.
function isLikelyPdf(buf) {
if (!(buf instanceof ArrayBuffer) || buf.byteLength < 8) return false;
return new TextDecoder().decode(new Uint8Array(buf, 0, 5)) === '%PDF-';
}
if (!isLikelyPdf(arrayBuffer)) {
throw new Error('Input is not a recognizable PDF; refusing to load.');
}
// Structural repair should be done server-side (qpdf/mutool) before retry. Try / catch
try {
const pdf = await getDocument({ data: arrayBuffer }).promise;
} catch (err) {
if (/Catalog object is not a dictionary/i.test(err?.message)) {
// Root/catalog is unusable; route user to repair/regenerate the file.
throw new Error('This PDF is too corrupt to open (bad catalog). Please re-export it.', { cause: err });
}
throw err;
} Prevention
- Validate files are real PDFs (magic %PDF-) and complete before calling getDocument.
- Repair corrupt PDFs with qpdf/mutool/ghostscript before loading.
- Verify checksums/sizes against the source after downloads.
- Reject non-PDF uploads at the trust boundary rather than relying on PDF.js to fail.
When it happens
Trigger: getDocument() loads a PDF whose trailer /Root indirect reference resolves to a non-dictionary object, or whose xref table is corrupt so the catalog ref points at the wrong object. The Catalog constructor runs during initial document setup, so this fails the whole load.
Common situations: Truncated or partially-written PDF file; corrupt xref/cross-reference stream pointing /Root at garbage; a non-PDF file (or a PDF header glued to other data) handed to getDocument(); a file that was repaired badly by a tool that lost the catalog.
Related errors
- Invalid top-level pages dictionary.
- Page count in top-level pages dictionary is not an integer.
- PageLabel is not a dictionary.
- Invalid type in PageLabel dictionary.
- Invalid style in PageLabel dictionary.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/a27129882500d9cf.
Report an issue: GitHub.