{"record":{"id":"16886121cbb3628d","repo":"mozilla/pdf.js","slug":"found-dnl-marker-0xffdc-while-parsing-scan-data","errorCode":null,"errorMessage":"Found DNL marker (0xFFDC) while parsing scan data","messagePattern":"Found DNL marker \\(0xFFDC\\) while parsing scan data","errorType":"exception","errorClass":"DNLMarkerError","httpStatus":null,"severity":"warning","filePath":"src/core/jpg.js","lineNumber":157,"sourceCode":"  let bitsData = 0,\n    bitsCount = 0;\n\n  function readBit() {\n    if (bitsCount > 0) {\n      bitsCount--;\n      return (bitsData >> bitsCount) & 1;\n    }\n    bitsData = data[offset++];\n    if (bitsData === 0xff) {\n      const nextByte = data[offset++];\n      if (nextByte) {\n        if (nextByte === /* DNL = */ 0xdc && parseDNLMarker) {\n          offset += 2; // Skip marker length.\n\n          const scanLines = view.getUint16(offset);\n          offset += 2;\n          if (scanLines > 0 && scanLines !== frame.scanLines) {\n            throw new DNLMarkerError(\n              \"Found DNL marker (0xFFDC) while parsing scan data\",\n              scanLines\n            );\n          }\n        } else if (nextByte === /* EOI = */ 0xd9) {\n          if (parseDNLMarker) {\n            // 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(","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/jpg.js#L139-L175","documentation":"Thrown as DNLMarkerError during JPEG scan parsing when a 0xFFDC (DNL - Define Number of Lines) marker is encountered inside the scan data and the scanLines it declares differs from the frame's expected scanLines. pdf.js treats this as a recoverable signal to redefine the image height. Note: parseDNLMarker must be true for this branch.","triggerScenarios":"Decoding a JPEG whose scan terminates early and emits a DNL marker declaring a non-zero line count that conflicts with the SOF frame height. Triggered by getDocument rendering of a DCTDecode image, with parseDNLMarker enabled (typically for images whose declared height was deliberately oversized).","commonSituations":"PDFs that embed JPEGs with a deliberately inflated SOF height and rely on the DNL marker to convey the true height; corrupt JPEGs; the known test cases issue10880/issue10989/issue15492 referenced in the source.","solutions":["Let pdf.js handle it: DNLMarkerError carries a scanLines field and is caught internally to correct the height — verify you are not unwrapping and rethrowing it as fatal.","Re-encode the JPEG with a correct SOF height to avoid the DNL marker entirely.","If you call the jpg decoder directly, pass parseDNLMarker=false to ignore DNL (will instead hit EOI handling).","Repair the source PDF/image so the JPEG SOF matches the actual line count."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// External pre-validation of JPEG DNL behavior is impractical; instead validate\n// that the JPEG's SOF height is plausible relative to the stream length:\nfunction jpegHeightPlausible(scanLines, byteLength) {\n  return scanLines > 0 && byteLength > scanLines; // very rough sanity\n}","typeGuard":"function isRecoverableDnlError(err) {\n  return err?.name === 'DNLMarkerError' && typeof err.scanLines === 'number';\n}","tryCatchPattern":"// pdf.js handles DNLMarkerError internally; only relevant if you call the\n// decoder directly:\ntry { decodeScan(...); }\ncatch (err) {\n  if (err?.name === 'DNLMarkerError') {\n    frame.scanLines = err.scanLines; // adopt corrected height\n  } else throw err;\n}","preventionTips":["Prefer letting pdf.js handle DNLMarkerError; do not rethrow it as fatal.","Encode JPEGs with a correct SOF height to avoid emitting DNL markers.","Validate JPEGs with jpegtran before embedding."],"tags":["pdf","jpeg","dctdecode","dnl-marker","recoverable"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}