mozilla/pdf.js · warning · FormatError
FontFile should be a stream
Error message
FontFile should be a stream
What it means
Thrown inside translateFont() when a font descriptor's /FontFile, /FontFile2, or /FontFile3 entry exists but is not a BaseStream (i.e. not a PDF stream object). Embedded font programs must be stream objects carrying the raw font bytes; a non-stream value means the reference is broken. The guard wraps the entire font-file fetch in a try/catch that honors options.ignoreErrors, so with the default render path it degrades to a warning and substitutes a fallback font.
Source
Thrown at src/core/evaluator.js:4620
}
if (!(fontName instanceof Name)) {
throw new FormatError("invalid font name");
}
let fontFile, fontFileN, subtype, length1, length2, length3;
try {
for (const n of ["FontFile", "FontFile2", "FontFile3"]) {
fontFile = descriptor.get(n);
if (fontFile) {
fontFileN = n;
break;
}
}
if (fontFile) {
if (!(fontFile instanceof BaseStream)) {
throw new FormatError("FontFile should be a stream");
} else {
if (fontFile.isAsync) {
const bytes = await fontFile.asyncGetBytes();
if (bytes) {
fontFile = new Stream(bytes, 0, bytes.length, fontFile.dict);
}
}
if (fontFile.isEmpty) {
throw new FormatError("FontFile is empty");
}
}
}
} catch (ex) {
if (!this.options.ignoreErrors) {
throw ex;
}
warn(`translateFont - fetching "${fontName.name}" font file: "${ex}".`);
fontFile = null;View on GitHub (pinned to 5903d58d58)
Solutions
- Re-embed the font properly using the original source document and a conformant PDF exporter.
- Run qpdf --object-streams=disable or Ghostscript to repair the object stream and stream references.
- Rely on ignoreErrors (default) — PDF.js will warn and fall back to a standard font; rendering continues with substituted glyphs.
- If authoring, validate that each /FontFile* entry is an indirect reference to a stream with /Length, /Subtype (for FontFile3), and byte payload.
Example fix
// before
getDocument({ url, stopAtErrors: true }); // propagates the FormatError
// after
getDocument({ url }); // ignoreErrors=true -> warn + fallback font, render continues Defensive patterns
Strategy: validation
Validate before calling
// This error is already gated by options.ignoreErrors inside translateFont().
// Use the default render path (no stopAtErrors) to let PDF.js warn + fall back:
const pdf = await getDocument({ url }).promise;
// Bad FontFile references degrade to a warn() and a fallback standard font. Prevention
- Leave stopAtErrors at default (false) so corrupt FontFile refs warn instead of throw.
- When authoring, ensure /FontFile* entries are indirect references to streams with /Length and byte payload.
- Repair stream references with qpdf --object-streams=disable or Ghostscript.
When it happens
Trigger: A /FontDescriptor whose /FontFile* entry resolves to a dictionary, number, string, null, or dangling reference instead of a stream. Fires during translateFont() when the descriptor declares an embedded font program that is not actually a stream.
Common situations: Font subsetting/embedding bugs in PDF generators, broken indirect references after linearization corruption, or PDFs where an optimizer replaced the font stream with a stub. Also seen when a FontFile3 references a sub-stream that was dropped during object-stream compression.
Related errors
- FontFile is empty
- Encoding is not a Name nor a Dict
- Invalid entry in 'Differences' array: ${data}
- Max size of CID is 65,535
- invalid font Subtype
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/535e83aef03e284e.
Report an issue: GitHub.