{"record":{"id":"53184b2161f68055","repo":"mozilla/pdf.js","slug":"unsupported-cmap-format","errorCode":null,"errorMessage":"unsupported cmap: ${format}","messagePattern":"unsupported cmap: (.+?)","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/font_renderer.js","lineNumber":97,"sourceCode":"      }\n    }\n    return ranges;\n  } else if (format === 12) {\n    const groups = view.getUint32(start + offset + 12);\n    p = start + offset + 16;\n    ranges = [];\n    for (i = 0; i < groups; i++) {\n      start = view.getUint32(p);\n      ranges.push({\n        start,\n        end: view.getUint32(p + 4),\n        idDelta: view.getUint32(p + 8) - start,\n      });\n      p += 12;\n    }\n    return ranges;\n  }\n  throw new FormatError(`unsupported cmap: ${format}`);\n}\n\nfunction parseCff(data, start, end, seacAnalysisEnabled) {\n  const properties = {};\n  const parser = new CFFParser(\n    new Stream(data, start, end - start),\n    properties,\n    seacAnalysisEnabled\n  );\n  const cff = parser.parse();\n  return {\n    glyphs: cff.charStrings.objects,\n    subrs: cff.topDict.privateDict?.subrsIndex?.objects,\n    gsubrs: cff.globalSubrIndex?.objects,\n    isCFFCIDFont: cff.isCIDFont,\n    fdSelect: cff.fdSelect,\n    fdArray: cff.fdArray,\n  };","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/font_renderer.js#L79-L115","documentation":"Thrown by parseCmap() in font_renderer.js when the font's cmap (character-to-glyph mapping) subtable has a format other than 4 (segment mapping) or 12 (segmented coverage). Only formats 4 and 12 are implemented in the font-rendering path; other formats (0, 2, 6, 13, 14, etc.) are rejected.","triggerScenarios":"Calling parseCmap(data, start, end) where view.getUint16(start + offset) yields a format value that is neither 4 nor 12. This is invoked during font compilation (CompiledFont.setupPath) when building glyph path data for rendering.","commonSituations":"Fonts with legacy cmap formats (format 0 byte encoding, format 2 high-byte mapping for CJK, format 6 trimmed table, format 13 many-to-one, or format 14 variation selectors). Non-standard or minimally-built embedded fonts in PDFs. Fonts designed for specialized encodings that only ship format 6.","solutions":["Use a font tool (fonttools/pyftsubset, FontForge) to convert the cmap to format 4 or 12 before embedding.","Replace the problematic embedded font in the PDF with a standard font that has a format-4 or format-12 cmap.","Update to the latest pdf.js version — newer versions may add support for additional cmap formats.","If the font is system-provided, install a version that includes a format-4 cmap subtable."],"exampleFix":"# before — subsetting with fonttools leaves format 0 cmap\npyftsubset font.ttf --unicodes=U+0041-005A\n\n# after — force cmap format 4 output\npyftsubset font.ttf --unicodes=U+0041-U+005A --layout-features='*' --no-hinting\nttx -o fixed.ttf font.ttx  # ensure format 4 subtable is present","handlingStrategy":"validation","validationCode":"// Server-side: check font cmap format before embedding\nconst opentype = require('opentype.js');\nfunction hasSupportedCmap(fontPath) {\n  const font = opentype.loadSync(fontPath);\n  const cmap = font.tables.cmap;\n  const formats = cmap.encodingRecords.map(r => {\n    // format is read from the subtable; opentype.js resolves this\n    return r.subtable ? r.subtable.format : null;\n  });\n  return formats.some(f => f === 4 || f === 12);\n}","typeGuard":null,"tryCatchPattern":"// Font rendering errors are caught internally by CompiledFont.getPath\n// (font_renderer.js:823 caches the Error and re-throws on subsequent calls).\n// At the display API level:\ntry {\n  await page.render(renderParams).promise;\n} catch (err) {\n  if (err.message?.includes('unsupported cmap')) {\n    console.warn('Font cmap format not supported for rendering; glyphs may be missing.');\n  } else { throw err; }\n}","preventionTips":["Ensure embedded fonts include cmap subtable format 4 (BMP) or 12 (full Unicode).","Use pyftsubset with --no-hinting to normalize cmap output.","Run ots-sanitize on fonts before embedding to catch missing/unsupported cmap formats."],"tags":["font","cmap","font-rendering","truetype","opentype","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}