mozilla/pdf.js · error · FormatError

Invalid header in flate stream: ${cmf}, ${flg}

Error message

Invalid header in flate stream: ${cmf}, ${flg}

What it means

Thrown by the FlateStream constructor when reading the two-byte zlib header (CMF, FLG) yields -1 for either byte, meaning the underlying stream is empty or truncated before the deflate data begins. A valid zlib stream must start with these two header bytes; their absence means the stream is not a deflate stream at all, or was cut off. This is the first of four sequential header-validation guards in the FlateStream constructor.

Source

Thrown at src/core/flate_stream.js:136

    0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,
    0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000,
  ]),
  5,
];

class FlateStream extends DecodeStream {
  #isAsync = true;

  constructor(str, maybeLength) {
    super(maybeLength);

    this.stream = str;
    this.dict = str.dict;

    const cmf = str.getByte();
    const flg = str.getByte();
    if (cmf === -1 || flg === -1) {
      throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`);
    }
    if ((cmf & 0x0f) !== 0x08) {
      throw new FormatError(
        `Unknown compression method in flate stream: ${cmf}, ${flg}`
      );
    }
    if (((cmf << 8) + flg) % 31 !== 0) {
      throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`);
    }
    if (flg & 0x20) {
      throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`);
    }

    this.codeSize = 0;
    this.codeBuf = 0;
  }

  async getImageData(length, _decoderOptions) {

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Re-download or re-acquire the PDF to ensure stream completeness; verify the file size and integrity (e.g. MD5 check).
  2. Repair with qpdf --linearize or Ghostscript to rebuild stream lengths and re-encode filters.
  3. If authoring, verify each FlateDecode stream has non-zero length and valid zlib header bytes before writing.
  4. Catch the FormatError at the page level and degrade — other pages/streams are usually unaffected.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await page.render({ canvasContext, viewport });
} catch (e) {
  if (e.name === 'FormatError' && /Invalid header in flate stream/.test(e.message)) {
    // stream is empty or truncated — skip or use fallback rendering
  } else throw e;
}

Prevention

When it happens

Trigger: Decoding a PDF stream whose /Filter includes /FlateDecode but whose bytes are empty, shorter than 2 bytes, or not yet fetched (async). Fires during stream construction, which happens whenever PDF.js decodes a Flate-compressed stream (page content, fonts, images, XObjects, metadata).

Common situations: Truncated PDF downloads, corrupt stream /Length values pointing past real data, empty streams from buggy generators that declared FlateDecode but wrote no payload, or async fetch failures where the stream reported EOF prematurely. Very common in PDFs transferred over unreliable networks.

Related errors


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