mozilla/pdf.js · error · FormatError

Required "head" table is not found

Error message

Required "head" table is not found

What it means

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.

Source

Thrown at src/core/fonts.js:2961

    if (!hintsValid) {
      delete tables.fpgm;
      delete tables.prep;
      delete tables["cvt "];
    }

    // Ensure the hmtx table contains the advance width and
    // sidebearings information for numGlyphs in the maxp table
    sanitizeMetrics(
      font,
      tables.hhea,
      tables.hmtx,
      tables.head,
      numGlyphsOut,
      dupFirstEntry
    );

    if (!tables.head) {
      throw new FormatError('Required "head" table is not found');
    }

    sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);

    let missingGlyphs = Object.create(null);
    if (isTrueType) {
      const glyphsInfo = sanitizeGlyphLocations(
        tables.loca,
        tables.glyf,
        numGlyphs,
        isGlyphLocationsLong,
        hintsValid,
        dupFirstEntry,
        maxSizeOfInstructions
      );
      missingGlyphs = glyphsInfo.missingGlyphs;

      // Some fonts have incorrect maxSizeOfInstructions values, so we use

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Replace the font with a complete, valid copy that includes a head table.
  2. Rebuild the font with fonttools (load + save) to regenerate the head table.
  3. Validate the embedded font stream with ots-sanitize before deployment.
  4. If generating PDFs, ensure font embedding includes all mandatory tables.

Example fix

# rebuild head table via fonttools round-trip
from fontTools import ttLib
font = ttLib.TTFont('broken.ttf')
# accessing font['head'] forces fontTools to parse/rebuild
_ = font['head'].unitsPerEm
font.save('fixed.ttf')
Defensive patterns

Strategy: validation

Validate before calling

// Server-side: verify font has head table
// from fontTools import ttLib
// font = ttLib.TTFont('font.ttf')
// assert 'head' in font, 'Font missing head table'

Try / catch

try {
  await page.render(renderParams).promise;
} catch (err) {
  if (err.message?.includes('Required "head" table is not found')) {
    console.error('Font missing head table; replace embedded font.');
  } else { throw err; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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