{"record":{"id":"fc09fc2948c3d130","repo":"mozilla/pdf.js","slug":"bad-fcheck-in-flate-stream-cmf-flg","errorCode":null,"errorMessage":"Bad FCHECK in flate stream: ${cmf}, ${flg}","messagePattern":"Bad FCHECK in flate stream: (.+?), (.+?)","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/flate_stream.js","lineNumber":144,"sourceCode":"\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) {\n    const data = await this.asyncGetBytes();\n    if (!data) {\n      return this.getBytes(length);\n    }\n    if (data.length <= length) {\n      return data;\n    }\n    return data.subarray(0, length);","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/flate_stream.js#L126-L162","documentation":"Thrown by the FlateStream constructor when the FCHECK invariant (((CMF<<8)+FLG) % 31 !== 0) fails. RFC 1950 requires that the 16-bit value formed by CMF and FLG be a multiple of 31 so decoders can detect header corruption. A failure means the two header bytes are inconsistent — either truncated, bit-flipped, or not actually a zlib header. This is the third of four sequential header guards.","triggerScenarios":"A /FlateDecode stream whose first two bytes are present and the method nibble is 8, but the modulo-31 checksum is wrong — indicating byte-level corruption of the header or a header that merely happens to have CM=8. Fires during FlateStream construction before any actual deflate decoding begins.","commonSituations":"Bit-level corruption from storage/network errors, PDFs processed by tools that patched bytes incorrectly, or generators with off-by-one header-encoding bugs. Less common than truncation but typical of partially-recovered or repaired PDFs.","solutions":["Re-acquire the PDF from a trusted source to rule out bit-rot or transfer corruption.","Repair with qpdf (which can often decode past minor corruption) or re-export via Ghostscript.","Catch at the page level and continue rendering other pages; this error is stream-local.","If authoring, run your zlib output through a decoder round-trip test to verify the header checksum before publishing."],"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' && /Bad FCHECK in flate stream/.test(e.message)) {\n    // zlib header checksum failed — bit-level corruption; re-acquire the PDF\n  } else throw e;\n}","preventionTips":["Re-acquire PDFs from a trusted source to rule out bit-rot or transfer corruption.","Repair with qpdf (can often decode past minor corruption) or re-export via Ghostscript.","Run a round-trip zlib decode test on authored streams before publishing."],"tags":["pdf","flate","zlib","fcheck","stream","corruption","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}