{"record":{"id":"201a5411b98a43c7","repo":"mozilla/pdf.js","slug":"unknown-operator-v","errorCode":null,"errorMessage":"unknown operator: ${v}","messagePattern":"unknown operator: (.+?)","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/font_renderer.js","lineNumber":716,"sourceCode":"            y = yb + stack.shift();\n            x = xb + (stack.length === 1 ? stack.shift() : 0);\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n            if (stack.length === 0) {\n              break;\n            }\n\n            xa = x;\n            ya = y + stack.shift();\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb + stack.shift();\n            y = yb + (stack.length === 1 ? stack.shift() : 0);\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          break;\n        default:\n          if (v < 32) {\n            throw new FormatError(`unknown operator: ${v}`);\n          }\n          if (v < 247) {\n            stack.push(v - 139);\n          } else if (v < 251) {\n            stack.push((v - 247) * 256 + code[i++] + 108);\n          } else if (v < 255) {\n            stack.push(-(v - 251) * 256 - code[i++] - 108);\n          } else {\n            stack.push(view.getInt32(i) / 65536);\n            i += 4;\n          }\n          break;\n      }\n      if (stackClean) {\n        stack.length = 0;\n      }\n    }\n  }","sourceCodeStart":698,"sourceCodeEnd":734,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/font_renderer.js#L698-L734","documentation":"Thrown during CFF charstring interpretation when a single-byte value v is less than 32 but does not match any recognized Type 2 operator (1=hstem, 3-vstem, 4-vmoveto, ..., 31=hvcurveto). Values below 32 are reserved as operators in Type 2 charstrings; an unrecognized one means the charstring data is corrupt or uses an unsupported operator.","triggerScenarios":"compileGlyphImpl() reads a byte v < 32 from a CFF charstring that doesn't correspond to any implemented operator case in the switch statement. The default branch checks v < 32 and throws. This is distinct from bytes >= 32 which are number-encoding operators.","commonSituations":"Corrupt CFF charstring bytecode caused by truncation, byte corruption, or misaligned reads from earlier bad data. Fonts produced by buggy CFF compilers. Charstrings that use obsolete Type 1 operators not valid in Type 2. The error is cached per-glyph and re-thrown on subsequent getPath calls for the same glyph.","solutions":["Obtain a clean copy of the font; round-trip it through fonttools (ttx export + recompile) to normalize charstrings.","Replace the embedded CFF font in the PDF with a known-good version.","If authoring CFF fonts, validate charstrings with fontTools.misc.psCharStrings or ots-sanitize before shipping.","Update pdf.js to the latest version for improved operator coverage."],"exampleFix":"# validate and repair CFF charstrings\npip install fonttools brotli\nttx broken.otf            # decompile to XML\nttx fixed.ttx            # recompile — normalizes operators\nots-sanitize fixed.otf   # verify compliance","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The error is cached per-glyph in CompiledFont.#compiledGlyphs and\n// re-thrown on subsequent getPath calls for the same glyph.\ntry {\n  await page.render(renderParams).promise;\n} catch (err) {\n  if (err.message?.startsWith('unknown operator:') && !err.message.includes('12')) {\n    console.warn('Corrupt CFF charstring operator; glyph not rendered.');\n  } else { throw err; }\n}","preventionTips":["Validate CFF fonts with ots-sanitize or fontbakery before embedding.","Rebuild fonts with fonttools to normalize charstring bytecode.","Keep PDF.js updated for improved operator coverage and error recovery."],"tags":["font","cff","charstring","opentype","font-rendering","corrupt-data","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}