mozilla/pdf.js · error · FormatError
unknown operator: 12 ${v}
Error message
unknown operator: 12 ${v} What it means
Thrown during CFF (Compact Font Format) charstring interpretation when a two-byte escape operator (first byte 12) has a second byte 'v' that is not one of the recognized flex operators (34=hflex, 35=flex, 36=hflex1, 37=flex1). CFF charstrings use byte 12 as an escape prefix for extended operators; only a subset is implemented in the font renderer.
Source
Thrown at src/core/font_renderer.js:539
yb = ya + stack.shift();
x = xb + stack.shift();
y = yb + stack.shift();
bezierCurveTo(xa, ya, xb, yb, x, y);
xa = x + stack.shift();
ya = y + stack.shift();
xb = xa + stack.shift();
yb = ya + stack.shift();
x = xb;
y = yb;
if (Math.abs(x - x0) > Math.abs(y - y0)) {
x += stack.shift();
} else {
y += stack.shift();
}
bezierCurveTo(xa, ya, xb, yb, x, y);
break;
default:
throw new FormatError(`unknown operator: 12 ${v}`);
}
break;
case 14: // endchar
if (stack.length >= 4) {
const achar = stack.pop();
const bchar = stack.pop();
y = stack.pop();
x = stack.pop();
cmds.save();
cmds.translate(x, y);
let cmap = lookupCmap(
font.cmap,
String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])
);
compileCharString(
font.glyphs[cmap.glyphId],
cmds,
font,View on GitHub (pinned to 5903d58d58)
Solutions
- Rebuild or re-export the font with fonttools (pyftsubset or ttx) to normalize charstrings to standard Type 2 operators.
- Replace the embedded font in the PDF with a well-formed CFF font.
- Update pdf.js — some operators may be added in future releases.
- If you produce CFF fonts, avoid deprecated two-byte operators (12-0 through 12-12) that the renderer doesn't implement.
Example fix
# normalize CFF charstrings with fonttools
from fontTools import ttLib
font = ttLib.TTFont('broken.otf')
font.save('fixed.otf') # round-trip normalizes charstring operators Defensive patterns
Strategy: try-catch
Validate before calling
// Validate CFF charstring operators with fonttools (Python, server-side)
// from fontTools.cff import CFFFontSet
// from fontTools.misc.psCharStrings import T2Charstring
// Check for unsupported 12-escaped operators by iterating charstrings.
function validateCffCharstrings(fontPath) {
// Requires running fonttools in a subprocess or server-side Python
// Returns list of glyphs with unsupported operators
} Try / catch
// CompiledFont.getPath catches compileGlyph errors internally and caches them.
// The re-thrown Error surfaces during page rendering:
try {
await page.render(renderParams).promise;
} catch (err) {
if (err.message?.startsWith('unknown operator: 12')) {
// Specific CFF glyph failed; page rendering continues for other glyphs
console.warn('Unsupported CFF flex operator in a glyph; glyph skipped.');
} else { throw err; }
} Prevention
- Round-trip CFF fonts through fonttools (ttx decompile + recompile) to normalize operators.
- Validate fonts with ots-sanitize before embedding in PDFs.
- Avoid CFF fonts from unreliable or experimental type foundries.
When it happens
Trigger: compileGlyphImpl() encounters byte 12 in a CFF Type 2 charstring, reads the next byte v, and v is not 34, 35, 36, or 37. Other valid two-byte CFF operators (e.g., 12-0 Copyright, 12-3 And, 12-9 vstem3) are not implemented in the rendering path.
Common situations: CFF/OpenType fonts with two-byte charstring operators beyond the flex family (e.g., 12-34 through 12-37). Corrupt charstring data where a byte is misread as operator 12. Non-standard fonts from niche type foundries using uncommon CFF operators. Note: the error is re-thrown from a cached Error in CompiledFont.getPath.
Related errors
- unknown operator: ${v}
- unsupported cmap: ${format}
- 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/abf4e959ffbcfd08.
Report an issue: GitHub.