mozilla/pdf.js · error · FormatError
unexpected EOF in bcmap
Error message
unexpected EOF in bcmap
What it means
Thrown by BinaryCMapStream.readNumber() (binary_cmap.js:78) when getByte() returns a negative value while decoding a variable-length, 7-bit-encoded integer from a binary CMap (.bcmap) stream. Binary CMaps are the packed CMap resources PDF.js fetches from cMapUrl to map character codes for CJK (Chinese/Japanese/Korean) fonts. The error means the byte stream ended before a complete integer could be read, so the resource is truncated or corrupt.
Source
Thrown at src/core/binary_cmap.js:78
class BinaryCMapStream extends Stream {
tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
constructor(data) {
super(
/* arrayBuffer = */ data,
/* start = */ 0,
/* length = */ data.length,
/* dict = */ null
);
}
readNumber() {
let n = 0;
let last;
do {
const b = this.getByte();
if (b < 0) {
throw new FormatError("unexpected EOF in bcmap");
}
last = !(b & 0x80);
n = (n << 7) | (b & 0x7f);
} while (!last);
return n;
}
readSigned() {
const n = this.readNumber();
return n & 1 ? ~(n >>> 1) : n >>> 1;
}
readHex(num, size) {
num.set(this.getBytes(size + 1));
}
readHexNumber(num, size) {
let last;View on GitHub (pinned to 5903d58d58)
Solutions
- Verify cMapUrl points to a complete, matching PDF.js CMap distribution (the 'external/bcmaps' folder of the same release) and that cMapPacked is left at its default true.
- Confirm the .bcmap file is served whole: fetch it directly, compare byte length to the source file, and check for proxy/CDN truncation or double-gzip.
- If a 404/HTML page is being served for the CMap, fix the URL/path so the correct binary resource resolves.
- Update PDF.js and its bundled CMaps to the same version so the bcmap format the reader expects matches the files shipped.
Example fix
// before: cMapUrl missing or wrong, packed CMap truncated
getDocument({ data, /* cMapUrl omitted */ });
// after: ship the matching packed CMap set and reference it
import { GlobalWorkerOptions } from 'pdfjs-dist';
getDocument({
data,
cMapUrl: 'https://mycdn.example.com/pdfjs/cmaps/',
cMapPacked: true, // default; ensures .bcmap files are fetched as binary
}).promise; Defensive patterns
Strategy: validation
Validate before calling
// Before getDocument, ensure packed CMaps are reachable and complete.
// Ship the cmaps folder from the SAME pdfjs-dist release you bundle.
const cMapUrl = new URL('cmaps/', import.meta.url).href; // local, complete copy
const params = { data, cMapUrl, cMapPacked: true };
// Optionally HEAD-check a known bcmap to confirm the dir is served:
// fetch(new URL('GBK-EUC-H.bcmap', cMapUrl), { method: 'HEAD' })
// .then(r => { if (!r.ok) throw new Error('CMap dir unreachable'); }); Try / catch
// CMap errors are caught internally and degrade font mapping; if you must surface them,
// wrap the rendering task and check for FormatError-like messages.
try {
await page.render({ canvasContext, viewport }).promise;
} catch (err) {
if (/bcmap|EOF/i.test(err?.message)) {
console.warn('CJK CMap resource problem; text may not map correctly', err);
} else throw err;
} Prevention
- Bundle the cmaps directory from the exact pdfjs-dist release your app uses.
- Keep cMapPacked at its default true and serve .bcmap files as binary (Content-Type application/octet-stream).
- Self-host CMaps rather than relying on a third-party CDN that may truncate responses.
- Pin your pdfjs-dist version so the bcmap format and reader stay aligned.
When it happens
Trigger: BinaryCMapReader.process() parses a .bcmap file (loaded via cMapUrl for a PDF using CJK fonts) whose data is shorter than its encoding declares, or whose leading bytes were consumed and a subsequent record expected more bytes than remain. Concretely: getByte() returning -1 (EOF) inside the do/while loop of readNumber() while a 7-bit varint is only partially read.
Common situations: cMapUrl pointing at an incomplete/edited CMap distribution; a CDN or reverse proxy truncating the .bcmap response (wrong Content-Length, gzip issue, partial range request); the fetch landing an HTML 404/500 page whose body is then parsed as binary CMap bytes; an outdated bcmap format shipped with a newer PDF.js build.
Related errors
- BinaryCMapReader.process: Invalid dataSize.
- BinaryCMapReader.process - unknown type: ${type}
- mapCidRange - ignoring data above MAX_MAP_RANGE.
- mapBfRange - ignoring data above MAX_MAP_RANGE.
- mapBfRangeToArray - ignoring data above MAX_MAP_RANGE.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/2a2a6c98a2f72f7e.
Report an issue: GitHub.