mozilla/pdf.js · error · EOIMarkerError
Found EOI marker (0xFFD9) while parsing scan data
Error message
Found EOI marker (0xFFD9) while parsing scan data
What it means
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.
Source
Thrown at src/core/jpg.js:182
// NOTE: only 8-bit JPEG images are supported in this decoder.
const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0);
// Heuristic to attempt to handle corrupt JPEG images with too
// large `scanLines` parameter, by falling back to the currently
// parsed number of scanLines when it's at least (approximately)
// one "half" order of magnitude smaller than expected (fixes
// issue10880.pdf, issue10989.pdf, issue15492.pdf).
if (
maybeScanLines > 0 &&
Math.round(frame.scanLines / maybeScanLines) >= 5
) {
throw new DNLMarkerError(
"Found EOI marker (0xFFD9) while parsing scan data, " +
"possibly caused by incorrect `scanLines` parameter",
maybeScanLines
);
}
}
throw new EOIMarkerError(
"Found EOI marker (0xFFD9) while parsing scan data"
);
}
throw new JpegError(
`unexpected marker ${((bitsData << 8) | nextByte).toString(16)}`
);
}
// unstuff 0
}
bitsCount = 7;
return bitsData >>> 7;
}
function decodeHuffman(tree) {
let node = tree;
while (true) {
node = node[readBit()];
switch (typeof node) {View on GitHub (pinned to 5903d58d58)
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// Check JPEG byte length vs expected MCU count before decoding:
function jpegStreamProbablyComplete(bytes, frame) {
const expectedMcus = frame.mcusPerLine * frame.mcusPerColumn;
return bytes.length >= expectedMcus; // crude lower bound
} Type guard
function isEoiMarkerError(err) {
return err?.name === 'EOIMarkerError';
} Try / catch
try { await page.render({ canvasContext }).promise; }
catch (err) {
if (err?.name === 'EOIMarkerError' || /EOI marker/.test(err?.message || '')) {
console.warn('JPEG scan truncated; rendering partial image.');
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Found EOI marker (0xFFD9) while parsing scan data, possibly
- Found DNL marker (0xFFDC) while parsing scan data
- unexpected marker ${((bitsData << 8) | nextByte).toString(16
- Parent must be a dictionary.
- Kids must be an array.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/c632e9be7d5c8ee6.
Report an issue: GitHub.