mozilla/pdf.js · error · Error

cmap was not found

Error message

cmap was not found

What it means

parseAdobeCMap() expects Adobe's text CMap format, which must contain a `begincmap` ... `endcmap` block. The regex `/\bbegincmap\b[\s\S]+?\bendcmap\b/` returning null means the file is not a CMap at all, is truncated before the markers, or uses a different dialect. The parser cannot proceed because everything it extracts (CMapType, WMode, body) lives inside that block. This is the text-side counterpart of the bcmap type error and is the first integrity check on CMap source files.

Source

Thrown at external/cmapscompress/parse.mjs:19

/* Copyright 2014 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function parseAdobeCMap(content) {
  let m = /(\bbegincmap\b[\s\S]+?)\bendcmap\b/.exec(content);
  if (!m) {
    throw new Error("cmap was not found");
  }

  const body = m[1].replaceAll(/\r\n?/g, "\n");
  const result = {
    type: 1,
    wmode: 0,
    comment:
      "Copyright 1990-2009 Adobe Systems Incorporated.\nAll rights reserved.\nSee ./LICENSE",
    usecmap: null,
    body: [],
  };
  m = /\/CMapType\s+(\d+)\s+def\b/.exec(body);
  result.type = +m[1];
  m = /\/WMode\s+(\d+)\s+def\b/.exec(body);
  result.wmode = +m[1];
  m = /\/([\w-]+)\s+usecmap\b/.exec(body);
  if (m) {
    result.usecmap = m[1];

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Confirm the input is an Adobe text CMap: it should literally contain the tokens `begincmap` and `endcmap`.
  2. Redownload the CMap resource from https://github.com/adobe-type-tools/cmap-resources and re-extract cleanly.
  3. If processing a batch, skip non-CMap files (filter by a quick `includes('begincmap')` test) before calling parseAdobeCMap.
  4. Check the file is not empty or truncated (`ls -l`, `wc -l`).

Example fix

// before
const parsed = parseAdobeCMap(fs.readFileSync('external/cmaps/somefile', 'utf8'));
// after
const content = fs.readFileSync('external/cmaps/UniJIS-UCS2-H', 'utf8');
if (!/\bbegincmap\b[\s\S]+\bendcmap\b/.test(content)) {
  throw new Error(`${file} is not a valid Adobe CMap text file`);
}
const parsed = parseAdobeCMap(content);
Defensive patterns

Strategy: validation

Validate before calling

function parseCMapSafe(content, name = '<cmap>') {
  if (!/\bbegincmap\b[\s\S]+?\bendcmap\b/.test(content)) {
    throw new Error(`${name} is not an Adobe CMap (no begincmap/endcmap block)`);
  }
  return parseAdobeCMap(content);
}

Type guard

function isCMapText(content) {
  return typeof content === 'string' && /\bbegincmap\b/.test(content) && /\bendcmap\b/.test(content);
}

Try / catch

try {
  parsed = parseAdobeCMap(content);
} catch (e) {
  if (/cmap was not found/.test(e.message)) {
    console.warn(`skipping non-CMap file ${file}`);
    continue;
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a PostScript fragment, a CIDFont wrapper, an empty file, or a binary bcmap to parseAdobeCMap; a CMap file whose `begincmap`/`endcmap` keywords were altered or stripped; reading a file with the wrong encoding that defeats the word-boundary regex.

Common situations: Pointing `gulp cmaps` (or a custom compress run) at a directory containing non-CMap text files; a hand-downloaded CMap resource that was truncated; line-ending or BOM issues that break the regex (note the function normalizes CRLF but a leading BOM before `begincmap` could still matter).

Related errors


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