{"record":{"id":"ecce4b63d7592d71","repo":"mozilla/pdf.js","slug":"invalid-header-in-flate-stream-cmf-flg","errorCode":null,"errorMessage":"Invalid header in flate stream: ${cmf}, ${flg}","messagePattern":"Invalid header in flate stream: (.+?), (.+?)","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/flate_stream.js","lineNumber":136,"sourceCode":"    0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,\n    0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000,\n  ]),\n  5,\n];\n\nclass FlateStream extends DecodeStream {\n  #isAsync = true;\n\n  constructor(str, maybeLength) {\n    super(maybeLength);\n\n    this.stream = str;\n    this.dict = str.dict;\n\n    const cmf = str.getByte();\n    const flg = str.getByte();\n    if (cmf === -1 || flg === -1) {\n      throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`);\n    }\n    if ((cmf & 0x0f) !== 0x08) {\n      throw new FormatError(\n        `Unknown compression method in flate stream: ${cmf}, ${flg}`\n      );\n    }\n    if (((cmf << 8) + flg) % 31 !== 0) {\n      throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`);\n    }\n    if (flg & 0x20) {\n      throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`);\n    }\n\n    this.codeSize = 0;\n    this.codeBuf = 0;\n  }\n\n  async getImageData(length, _decoderOptions) {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/flate_stream.js#L118-L154","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Re-download or re-acquire the PDF to ensure stream completeness; verify the file size and integrity (e.g. MD5 check).","Repair with qpdf --linearize or Ghostscript to rebuild stream lengths and re-encode filters.","If authoring, verify each FlateDecode stream has non-zero length and valid zlib header bytes before writing.","Catch the FormatError at the page level and degrade — other pages/streams are usually unaffected."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await page.render({ canvasContext, viewport });\n} catch (e) {\n  if (e.name === 'FormatError' && /Invalid header in flate stream/.test(e.message)) {\n    // stream is empty or truncated — skip or use fallback rendering\n  } else throw e;\n}","preventionTips":["Verify PDF file integrity (size, MD5) before processing to rule out truncation.","Repair stream lengths with qpdf --linearize or Ghostscript.","Isolate per-page operations so one bad stream does not abort the whole document."],"tags":["pdf","flate","zlib","stream","format-error","truncation"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}