{"record":{"id":"7407fe14c309ab0a","repo":"mozilla/pdf.js","slug":"fdict-bit-set-in-flate-stream-cmf-flg","errorCode":null,"errorMessage":"FDICT bit set in flate stream: ${cmf}, ${flg}","messagePattern":"FDICT bit set in flate stream: (.+?), (.+?)","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/flate_stream.js","lineNumber":147,"sourceCode":"\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);\n  }\n\n  async asyncGetBytes() {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/flate_stream.js#L129-L165","documentation":"Thrown by the FlateStream constructor when the zlib header's FLG byte has bit 5 (0x20) set, indicating a preset dictionary (FDICT) is present. PDF.js's JavaScript DEFLATE decoder does not support preset dictionaries, so it rejects the stream outright rather than attempting decompression without the dictionary. The cmf and flg values are included in the message for diagnostics.","triggerScenarios":"Constructing a new FlateStream(stream, maybeLength) where the underlying stream's first two bytes form a zlib header with (flg & 0x20) !== 0. This occurs when PDF.js falls back to its JS decoder after the browser's native DecompressionStream API also fails on a stream that carries a preset dictionary.","commonSituations":"A PDF whose FlateDecode stream was compressed with a preset dictionary (rare in well-formed PDFs). Truncated or byte-corrupted PDF files where the header bytes coincidentally have the FDICT bit set. Hand-crafted or minimally-edited PDFs produced by non-standard tooling.","solutions":["Re-export or re-save the source PDF with a standard PDF library (e.g., Ghostscript, qpdf) to regenerate clean FlateDecode streams without preset dictionaries.","Validate the PDF with qpdf --check or a similar tool to confirm structural integrity before loading it with pdf.js.","If you control PDF generation, ensure zlib.deflate is called without a preset dictionary (no zdict argument).","Catch the error at the page-render level and fall back to a placeholder or re-fetch the document from the source."],"exampleFix":"// before — generating a compressed PDF stream with a dictionary\nconst deflated = zlib.deflateSync(data, { dictionary: presetDict });\n\n// after — omit the dictionary so the FLG FDICT bit is never set\nconst deflated = zlib.deflateSync(data);","handlingStrategy":"fallback","validationCode":"// Before loading, check the PDF's stream filters for FlateDecode and\n// pre-scan the first object stream bytes for the FDICT bit.\n// This requires access to raw PDF bytes — only feasible server-side.\nasync function checkFlateHeader(bytes) {\n  // find zlib-compressed streams; check FLG byte (byte index 1)\n  const flg = bytes[1];\n  if (flg & 0x20) {\n    return { ok: false, reason: 'FDICT bit set — preset dictionary not supported' };\n  }\n  return { ok: true };\n}","typeGuard":null,"tryCatchPattern":"// pdf.js display API: catch at the page/task level\ntry {\n  const page = await pdfDoc.getPage(pageNum);\n  const renderTask = page.render({ canvasContext, viewport });\n  await renderTask.promise;\n} catch (err) {\n  if (err instanceof Error && err.message.includes('FDICT bit set in flate stream')) {\n    console.warn('Unsupported zlib preset dictionary in stream; page may be incomplete.');\n    // render placeholder or skip\n  } else {\n    throw err;\n  }\n}","preventionTips":["Generate PDF FlateDecode streams without zlib preset dictionaries.","Validate PDFs with qpdf --check before serving to pdf.js.","Keep pdf.js updated — the native DecompressionStream path handles many cases before the JS fallback."],"tags":["flate","deflate","zlib","compression","pdf-stream","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}