{"record":{"id":"c632e9be7d5c8ee6","repo":"mozilla/pdf.js","slug":"found-eoi-marker-0xffd9-while-parsing-scan-data-c632e9","errorCode":null,"errorMessage":"Found EOI marker (0xFFD9) while parsing scan data","messagePattern":"Found EOI marker \\(0xFFD9\\) while parsing scan data","errorType":"exception","errorClass":"EOIMarkerError","httpStatus":null,"severity":"error","filePath":"src/core/jpg.js","lineNumber":182,"sourceCode":"            // NOTE: only 8-bit JPEG images are supported in this decoder.\n            const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0);\n            // Heuristic to attempt to handle corrupt JPEG images with too\n            // large `scanLines` parameter, by falling back to the currently\n            // parsed number of scanLines when it's at least (approximately)\n            // one \"half\" order of magnitude smaller than expected (fixes\n            // issue10880.pdf, issue10989.pdf, issue15492.pdf).\n            if (\n              maybeScanLines > 0 &&\n              Math.round(frame.scanLines / maybeScanLines) >= 5\n            ) {\n              throw new DNLMarkerError(\n                \"Found EOI marker (0xFFD9) while parsing scan data, \" +\n                  \"possibly caused by incorrect `scanLines` parameter\",\n                maybeScanLines\n              );\n            }\n          }\n          throw new EOIMarkerError(\n            \"Found EOI marker (0xFFD9) while parsing scan data\"\n          );\n        }\n        throw new JpegError(\n          `unexpected marker ${((bitsData << 8) | nextByte).toString(16)}`\n        );\n      }\n      // unstuff 0\n    }\n    bitsCount = 7;\n    return bitsData >>> 7;\n  }\n\n  function decodeHuffman(tree) {\n    let node = tree;\n    while (true) {\n      node = node[readBit()];\n      switch (typeof node) {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/jpg.js#L164-L200","documentation":"Thrown as EOIMarkerError when an EOI (0xFFD9) marker is reached during scan parsing and pdf.js cannot recover (either parseDNLMarker is false, or the heuristic for over-large height did not apply). It signals premature end of the JPEG scan data.","triggerScenarios":"Decoding a JPEG whose scan ends with 0xFFD9 before the expected number of MCUs, with parseDNLMarker=false OR with a height that does not meet the 5x recovery threshold. Reached during DCTDecode image rendering.","commonSituations":"Truncated JPEG streams (download/interruption), corrupt image data, or PDFs whose SOF height exactly matches reality but the scan data is short. Distinct from DNLMarkerError in that no recovery is attempted.","solutions":["Verify the JPEG byte stream is complete and not truncated (check stream length against expected).","Re-embed a complete JPEG in the source PDF.","If you wrap the decoder, catch EOIMarkerError and present whatever partial scan data was produced.","Enable parseDNLMarker (default in the pdf.js image path) so the recoverable variant (error 157) is attempted first."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Check JPEG byte length vs expected MCU count before decoding:\nfunction jpegStreamProbablyComplete(bytes, frame) {\n  const expectedMcus = frame.mcusPerLine * frame.mcusPerColumn;\n  return bytes.length >= expectedMcus; // crude lower bound\n}","typeGuard":"function isEoiMarkerError(err) {\n  return err?.name === 'EOIMarkerError';\n}","tryCatchPattern":"try { await page.render({ canvasContext }).promise; }\ncatch (err) {\n  if (err?.name === 'EOIMarkerError' || /EOI marker/.test(err?.message || '')) {\n    console.warn('JPEG scan truncated; rendering partial image.');\n  } else throw err;\n}","preventionTips":["Verify JPEG stream integrity (length, no truncation) before embedding.","Enable parseDNLMarker so the recoverable DNLMarkerError path is attempted first.","Re-embed complete JPEGs in source PDFs."],"tags":["pdf","jpeg","dctdecode","eoi-marker","truncated"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}