{"record":{"id":"abf4e959ffbcfd08","repo":"mozilla/pdf.js","slug":"unknown-operator-12-v","errorCode":null,"errorMessage":"unknown operator: 12 ${v}","messagePattern":"unknown operator: 12 (.+?)","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/font_renderer.js","lineNumber":539,"sourceCode":"              yb = ya + stack.shift();\n              x = xb + stack.shift();\n              y = yb + stack.shift();\n              bezierCurveTo(xa, ya, xb, yb, x, y);\n              xa = x + stack.shift();\n              ya = y + stack.shift();\n              xb = xa + stack.shift();\n              yb = ya + stack.shift();\n              x = xb;\n              y = yb;\n              if (Math.abs(x - x0) > Math.abs(y - y0)) {\n                x += stack.shift();\n              } else {\n                y += stack.shift();\n              }\n              bezierCurveTo(xa, ya, xb, yb, x, y);\n              break;\n            default:\n              throw new FormatError(`unknown operator: 12 ${v}`);\n          }\n          break;\n        case 14: // endchar\n          if (stack.length >= 4) {\n            const achar = stack.pop();\n            const bchar = stack.pop();\n            y = stack.pop();\n            x = stack.pop();\n            cmds.save();\n            cmds.translate(x, y);\n            let cmap = lookupCmap(\n              font.cmap,\n              String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])\n            );\n            compileCharString(\n              font.glyphs[cmap.glyphId],\n              cmds,\n              font,","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/font_renderer.js#L521-L557","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# normalize CFF charstrings with fonttools\nfrom fontTools import ttLib\nfont = ttLib.TTFont('broken.otf')\nfont.save('fixed.otf')  # round-trip normalizes charstring operators","handlingStrategy":"try-catch","validationCode":"// Validate CFF charstring operators with fonttools (Python, server-side)\n// from fontTools.cff import CFFFontSet\n// from fontTools.misc.psCharStrings import T2Charstring\n// Check for unsupported 12-escaped operators by iterating charstrings.\nfunction validateCffCharstrings(fontPath) {\n  // Requires running fonttools in a subprocess or server-side Python\n  // Returns list of glyphs with unsupported operators\n}","typeGuard":null,"tryCatchPattern":"// CompiledFont.getPath catches compileGlyph errors internally and caches them.\n// The re-thrown Error surfaces during page rendering:\ntry {\n  await page.render(renderParams).promise;\n} catch (err) {\n  if (err.message?.startsWith('unknown operator: 12')) {\n    // Specific CFF glyph failed; page rendering continues for other glyphs\n    console.warn('Unsupported CFF flex operator in a glyph; glyph skipped.');\n  } else { throw err; }\n}","preventionTips":["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."],"tags":["font","cff","charstring","opentype","font-rendering","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}