mozilla/pdf.js · error · FormatError
invalid font Subtype
Error message
invalid font Subtype
What it means
Thrown by preEvaluateFont() when a font dictionary's /Subtype entry is not a PDF Name object. /Subtype distinguishes font kinds (TrueType, Type1, Type0/CIDFontType0/2, Type3, etc.) and must always be a Name; without it the evaluator cannot route the font through the correct loader. This is the top-level guard before any font-type-specific dispatch.
Source
Thrown at src/core/evaluator.js:4292
const encoding = properties.defaultEncoding;
for (let charCode = 0; charCode < 256; charCode++) {
if (charCode in differences && widthsByGlyphName[differences[charCode]]) {
widths[charCode] = widthsByGlyphName[differences[charCode]];
continue;
}
if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
widths[charCode] = widthsByGlyphName[encoding[charCode]];
continue;
}
}
return widths;
}
preEvaluateFont(dict) {
const baseDict = dict;
let type = dict.get("Subtype");
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.");
}View on GitHub (pinned to 5903d58d58)
Solutions
- Repair the PDF with qpdf --linearize or Ghostscript to rebuild font dictionaries.
- If you produce PDFs, ensure /Subtype is written as a Name (e.g. /TrueType not "TrueType").
- Use stopAtErrors: true only if you need isolation; otherwise let ignoreErrors handle it and accept degraded rendering.
- File a PDF.js bug if the PDF renders cleanly in Acrobat — defensive fallbacks may be worth adding.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await page.render({ canvasContext, viewport });
} catch (e) {
if (e.name === 'FormatError' && /invalid font Subtype/.test(e.message)) {
// font has no valid Subtype — render with fallback
} else throw e;
} Prevention
- Validate font dictionaries with qpdf --check before processing.
- When authoring, always write /Subtype as a Name (/TrueType, /Type1, /Type0, /Type3).
- Use stopAtErrors: true with per-page isolation so bad fonts don't crash the whole load.
When it happens
Trigger: Any font dictionary (top-level Font or a Type0 descendant) whose /Subtype is missing, null, a string, or any non-Name type. Fires during preEvaluateFont() which is called from the font-loading path on every font referenced by a page.
Common situations: Truncated or hand-edited PDFs, generators that wrote /Subtype as a literal string instead of a Name, or PDFs damaged by partial download/linearization. Often co-occurs with other font structural errors.
Related errors
- Invalid entry in 'Differences' array: ${data}
- Encoding is not a Name nor a Dict
- Max size of CID is 65,535
- Descendant fonts are not specified
- Descendant font is not a dictionary.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/d4c4d9d5e0892334.
Report an issue: GitHub.