mozilla/pdf.js · error · FormatError
unsupported cmap: ${format}
Error message
unsupported cmap: ${format} What it means
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.
Source
Thrown at src/core/font_renderer.js:97
}
}
return ranges;
} else if (format === 12) {
const groups = view.getUint32(start + offset + 12);
p = start + offset + 16;
ranges = [];
for (i = 0; i < groups; i++) {
start = view.getUint32(p);
ranges.push({
start,
end: view.getUint32(p + 4),
idDelta: view.getUint32(p + 8) - start,
});
p += 12;
}
return ranges;
}
throw new FormatError(`unsupported cmap: ${format}`);
}
function parseCff(data, start, end, seacAnalysisEnabled) {
const properties = {};
const parser = new CFFParser(
new Stream(data, start, end - start),
properties,
seacAnalysisEnabled
);
const cff = parser.parse();
return {
glyphs: cff.charStrings.objects,
subrs: cff.topDict.privateDict?.subrsIndex?.objects,
gsubrs: cff.globalSubrIndex?.objects,
isCFFCIDFont: cff.isCIDFont,
fdSelect: cff.fdSelect,
fdArray: cff.fdArray,
};View on GitHub (pinned to 5903d58d58)
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.
Example fix
# before — subsetting with fonttools leaves format 0 cmap pyftsubset font.ttf --unicodes=U+0041-005A # after — force cmap format 4 output pyftsubset font.ttf --unicodes=U+0041-U+005A --layout-features='*' --no-hinting ttx -o fixed.ttf font.ttx # ensure format 4 subtable is present
Defensive patterns
Strategy: validation
Validate before calling
// Server-side: check font cmap format before embedding
const opentype = require('opentype.js');
function hasSupportedCmap(fontPath) {
const font = opentype.loadSync(fontPath);
const cmap = font.tables.cmap;
const formats = cmap.encodingRecords.map(r => {
// format is read from the subtable; opentype.js resolves this
return r.subtable ? r.subtable.format : null;
});
return formats.some(f => f === 4 || f === 12);
} Try / catch
// Font rendering errors are caught internally by CompiledFont.getPath
// (font_renderer.js:823 caches the Error and re-throws on subsequent calls).
// At the display API level:
try {
await page.render(renderParams).promise;
} catch (err) {
if (err.message?.includes('unsupported cmap')) {
console.warn('Font cmap format not supported for rendering; glyphs may be missing.');
} else { throw err; }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- unknown operator: 12 ${v}
- unknown operator: ${v}
- Unicode ranges Bits > 123 are reserved for internal usage
- Required "maxp" table is not found
- "maxp" table has a wrong version number
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/53184b2161f68055.
Report an issue: GitHub.