{"record":{"id":"d4c4d9d5e0892334","repo":"mozilla/pdf.js","slug":"invalid-font-subtype","errorCode":null,"errorMessage":"invalid font Subtype","messagePattern":"invalid font Subtype","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/evaluator.js","lineNumber":4292,"sourceCode":"    const encoding = properties.defaultEncoding;\n    for (let charCode = 0; charCode < 256; charCode++) {\n      if (charCode in differences && widthsByGlyphName[differences[charCode]]) {\n        widths[charCode] = widthsByGlyphName[differences[charCode]];\n        continue;\n      }\n      if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {\n        widths[charCode] = widthsByGlyphName[encoding[charCode]];\n        continue;\n      }\n    }\n    return widths;\n  }\n\n  preEvaluateFont(dict) {\n    const baseDict = dict;\n    let type = dict.get(\"Subtype\");\n    if (!(type instanceof Name)) {\n      throw new FormatError(\"invalid font Subtype\");\n    }\n\n    let composite = false;\n    let hash;\n    if (type.name === \"Type0\") {\n      // If font is a composite\n      //  - get the descendant font\n      //  - set the type according to the descendant font\n      //  - get the FontDescriptor from the descendant font\n      const df = dict.get(\"DescendantFonts\");\n      if (!df) {\n        throw new FormatError(\"Descendant fonts are not specified\");\n      }\n      dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;\n\n      if (!(dict instanceof Dict)) {\n        throw new FormatError(\"Descendant font is not a dictionary.\");\n      }","sourceCodeStart":4274,"sourceCodeEnd":4310,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/evaluator.js#L4274-L4310","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await page.render({ canvasContext, viewport });\n} catch (e) {\n  if (e.name === 'FormatError' && /invalid font Subtype/.test(e.message)) {\n    // font has no valid Subtype — render with fallback\n  } else throw e;\n}","preventionTips":["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."],"tags":["pdf","font","subtype","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}