mozilla/pdf.js · error · FormatError
Descendant font is not a dictionary.
Error message
Descendant font is not a dictionary.
What it means
Thrown by preEvaluateFont() when a Type0 font's /DescendantFonts[0], after indirect-reference resolution, is not a Dictionary. The descendant must be a CIDFont dictionary carrying /Subtype, /CIDSystemInfo, /FontDescriptor, etc.; a non-dict value means the reference is broken or the producer wrote the wrong object. This guard protects the subsequent .get('Subtype') call.
Source
Thrown at src/core/evaluator.js:4309
if (!(type instanceof Name)) {
throw new FormatError("invalid font Subtype");
}
let composite = false;
let hash;
if (type.name === "Type0") {
// If font is a composite
// - get the descendant font
// - set the type according to the descendant font
// - get the FontDescriptor from the descendant font
const df = dict.get("DescendantFonts");
if (!df) {
throw new FormatError("Descendant fonts are not specified");
}
dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;
if (!(dict instanceof Dict)) {
throw new FormatError("Descendant font is not a dictionary.");
}
type = dict.get("Subtype");
if (!(type instanceof Name)) {
throw new FormatError("invalid font Subtype");
}
composite = true;
}
let firstChar = dict.get("FirstChar");
if (!Number.isInteger(firstChar)) {
firstChar = 0;
}
let lastChar = dict.get("LastChar");
if (!Number.isInteger(lastChar)) {
lastChar = composite ? 0xffff : 0xff;
}
const descriptor = dict.get("FontDescriptor");
const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode");View on GitHub (pinned to 5903d58d58)
Solutions
- Run qpdf --check to detect broken xrefs, then qpdf --linearize to rebuild the object graph.
- Re-export the source document to PDF using a different producer (Acrobat, Ghostscript, libreoffice).
- Catch per-page and degrade rendering rather than aborting the document.
- If you control the producer, ensure /DescendantFonts entries are indirect refs that resolve to CIDFont dicts.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await page.render({ canvasContext, viewport });
} catch (e) {
if (e.name === 'FormatError' && /Descendant font is not a dictionary/.test(e.message)) {
// dangling xref — skip page or use fallback font
} else throw e;
} Prevention
- Run qpdf --check to detect broken cross-reference tables before processing.
- Repair xrefs with qpdf --linearize or Ghostscript before rendering.
- When authoring, ensure /DescendantFonts entries resolve to CIDFont dictionaries.
When it happens
Trigger: A Type0 font whose /DescendantFonts array's first element resolves (via xref.fetchIfRef) to a primitive, null, stream, or dangling reference. Fires in preEvaluateFont() during font load for the relevant page.
Common situations: Dangling indirect references from broken cross-reference tables, PDFs edited by hand or by tools that did not preserve object graphs, or files corrupted during transfer/storage. Also possible after a faulty PDF/A conversion that stripped CIDFont dictionaries.
Related errors
- Descendant fonts are not specified
- Invalid entry in 'Differences' array: ${data}
- Encoding is not a Name nor a Dict
- Max size of CID is 65,535
- invalid font Subtype
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/cf4748c9286c71a2.
Report an issue: GitHub.