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

  1. Run qpdf --check to detect broken xrefs, then qpdf --linearize to rebuild the object graph.
  2. Re-export the source document to PDF using a different producer (Acrobat, Ghostscript, libreoffice).
  3. Catch per-page and degrade rendering rather than aborting the document.
  4. 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

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


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/cf4748c9286c71a2. Report an issue: GitHub.