mozilla/pdf.js · error · FormatError

unknown operator: ${v}

Error message

unknown operator: ${v}

What it means

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.

Source

Thrown at src/core/font_renderer.js:716

            y = yb + stack.shift();
            x = xb + (stack.length === 1 ? stack.shift() : 0);
            bezierCurveTo(xa, ya, xb, yb, x, y);
            if (stack.length === 0) {
              break;
            }

            xa = x;
            ya = y + stack.shift();
            xb = xa + stack.shift();
            yb = ya + stack.shift();
            x = xb + stack.shift();
            y = yb + (stack.length === 1 ? stack.shift() : 0);
            bezierCurveTo(xa, ya, xb, yb, x, y);
          }
          break;
        default:
          if (v < 32) {
            throw new FormatError(`unknown operator: ${v}`);
          }
          if (v < 247) {
            stack.push(v - 139);
          } else if (v < 251) {
            stack.push((v - 247) * 256 + code[i++] + 108);
          } else if (v < 255) {
            stack.push(-(v - 251) * 256 - code[i++] - 108);
          } else {
            stack.push(view.getInt32(i) / 65536);
            i += 4;
          }
          break;
      }
      if (stackClean) {
        stack.length = 0;
      }
    }
  }

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Obtain a clean copy of the font; round-trip it through fonttools (ttx export + recompile) to normalize charstrings.
  2. Replace the embedded CFF font in the PDF with a known-good version.
  3. If authoring CFF fonts, validate charstrings with fontTools.misc.psCharStrings or ots-sanitize before shipping.
  4. Update pdf.js to the latest version for improved operator coverage.

Example fix

# validate and repair CFF charstrings
pip install fonttools brotli
ttx broken.otf            # decompile to XML
ttx fixed.ttx            # recompile — normalizes operators
ots-sanitize fixed.otf   # verify compliance
Defensive patterns

Strategy: try-catch

Try / catch

// The error is cached per-glyph in CompiledFont.#compiledGlyphs and
// re-thrown on subsequent getPath calls for the same glyph.
try {
  await page.render(renderParams).promise;
} catch (err) {
  if (err.message?.startsWith('unknown operator:') && !err.message.includes('12')) {
    console.warn('Corrupt CFF charstring operator; glyph not rendered.');
  } else { throw err; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/201a5411b98a43c7. Report an issue: GitHub.