{"record":{"id":"3831feae538ee197","repo":"mozilla/pdf.js","slug":"required-head-table-is-not-found","errorCode":null,"errorMessage":"Required \"head\" table is not found","messagePattern":"Required \"head\" table is not found","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/fonts.js","lineNumber":2961,"sourceCode":"    if (!hintsValid) {\n      delete tables.fpgm;\n      delete tables.prep;\n      delete tables[\"cvt \"];\n    }\n\n    // Ensure the hmtx table contains the advance width and\n    // sidebearings information for numGlyphs in the maxp table\n    sanitizeMetrics(\n      font,\n      tables.hhea,\n      tables.hmtx,\n      tables.head,\n      numGlyphsOut,\n      dupFirstEntry\n    );\n\n    if (!tables.head) {\n      throw new FormatError('Required \"head\" table is not found');\n    }\n\n    sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);\n\n    let missingGlyphs = Object.create(null);\n    if (isTrueType) {\n      const glyphsInfo = sanitizeGlyphLocations(\n        tables.loca,\n        tables.glyf,\n        numGlyphs,\n        isGlyphLocationsLong,\n        hintsValid,\n        dupFirstEntry,\n        maxSizeOfInstructions\n      );\n      missingGlyphs = glyphsInfo.missingGlyphs;\n\n      // Some fonts have incorrect maxSizeOfInstructions values, so we use","sourceCodeStart":2943,"sourceCodeEnd":2979,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/fonts.js#L2943-L2979","documentation":"Thrown when the font's table directory lacks a 'head' table. The head table is mandatory — it carries the font's unitsPerEm, bbox, indexToLocFormat, and other critical metadata. Note that sanitizeMetrics is called with tables.head before this check (it tolerates a null head), but sanitizeHead() requires the table and the subsequent code reads head.data directly.","triggerScenarios":"After sanitizeMetrics completes, the check if (!tables.head) at line 2960 throws. This is reached for fonts that passed the earlier CFF divert check (had CFF + OTTO header + complete core tables) or TrueType fonts that passed the loca/glyf checks.","commonSituations":"A corrupt or severely stripped font missing the head table. A font file where the table directory is intact but the head table data was truncated. Non-standard fonts from unreliable sources. PDFs with damaged embedded font streams.","solutions":["Replace the font with a complete, valid copy that includes a head table.","Rebuild the font with fonttools (load + save) to regenerate the head table.","Validate the embedded font stream with ots-sanitize before deployment.","If generating PDFs, ensure font embedding includes all mandatory tables."],"exampleFix":"# rebuild head table via fonttools round-trip\nfrom fontTools import ttLib\nfont = ttLib.TTFont('broken.ttf')\n# accessing font['head'] forces fontTools to parse/rebuild\n_ = font['head'].unitsPerEm\nfont.save('fixed.ttf')","handlingStrategy":"validation","validationCode":"// Server-side: verify font has head table\n// from fontTools import ttLib\n// font = ttLib.TTFont('font.ttf')\n// assert 'head' in font, 'Font missing head table'\n","typeGuard":null,"tryCatchPattern":"try {\n  await page.render(renderParams).promise;\n} catch (err) {\n  if (err.message?.includes('Required \"head\" table is not found')) {\n    console.error('Font missing head table; replace embedded font.');\n  } else { throw err; }\n}","preventionTips":["Ensure all fonts include the mandatory head table before embedding.","Rebuild fonts with fonttools to regenerate missing core tables.","Validate fonts with ots-sanitize — it flags missing head as critical."],"tags":["font","head-table","required-table","truetype","opentype","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}