{"record":{"id":"d4808370e6aedd8b","repo":"mozilla/pdf.js","slug":"duplicate-exif-blocks-found","errorCode":null,"errorMessage":"Duplicate EXIF-blocks found.","messagePattern":"Duplicate EXIF-blocks found\\.","errorType":"exception","errorClass":"JpegError","httpStatus":null,"severity":"error","filePath":"src/core/jpg.js","lineNumber":847,"sourceCode":"          //       is fixed.\n          const { appData, oldOffset, newOffset } = readDataBlock(\n            data,\n            view,\n            offset\n          );\n          offset = newOffset;\n\n          // 'Exif\\x00\\x00'\n          if (\n            appData[0] === 0x45 &&\n            appData[1] === 0x78 &&\n            appData[2] === 0x69 &&\n            appData[3] === 0x66 &&\n            appData[4] === 0 &&\n            appData[5] === 0\n          ) {\n            if (exifOffsets) {\n              throw new JpegError(\"Duplicate EXIF-blocks found.\");\n            }\n            // Don't do the EXIF-block replacement here, see `JpegStream`,\n            // since that can modify the original PDF document.\n            exifOffsets = { exifStart: oldOffset + 6, exifEnd: newOffset };\n          }\n          fileMarker = view.getUint16(offset);\n          offset += 2;\n          continue;\n        case 0xffc0: // SOF0 (Start of Frame, Baseline DCT)\n        case 0xffc1: // SOF1 (Start of Frame, Extended DCT)\n        case 0xffc2: // SOF2 (Start of Frame, Progressive DCT)\n          // Skip marker length.\n          // Skip precision.\n          // Skip scanLines.\n          // Skip samplesPerLine.\n          numComponents = data[offset + (2 + 1 + 2 + 2)];\n          break markerLoop;\n        case 0xffff: // Fill bytes","sourceCodeStart":829,"sourceCodeEnd":865,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/jpg.js#L829-L865","documentation":"Thrown by canUseImageDecoder() while scanning APP1 segments. The EXIF spec allows exactly one APP1/Exif block; if a second segment matching the 'Exif\\x00\\x00' signature is found, the error fires. This guards the WebCodecs path which cannot handle multiple EXIF blobs.","triggerScenarios":"canUseImageDecoder encounters two APP1 (0xFFE1) segments both beginning with the 6-byte 'Exif\\x00\\x00' signature. The exifOffsets variable is already set when the second match is detected.","commonSituations":"A JPEG that was re-saved or edited by tools that append a new EXIF block without removing the old one. Some camera/editing pipelines produce duplicate APP1 segments. Relatively rare in PDF-embedded images but possible.","solutions":["Strip duplicate EXIF segments from the JPEG using exiftool or jpegtran before embedding in the PDF.","If you cannot modify the source, avoid the canUseImageDecoder fast-path and fall back to the software JPEG decoder (JpegImage.parse) which tolerates this.","Report the producing tool as non-compliant with the EXIF/JEITA specification."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { const r = JpegImage.canUseImageDecoder(data); }\ncatch (e) { if (e.name === 'JpegError' && /Duplicate EXIF/.test(e.message)) { /* use software decoder instead */ } else throw e; }","preventionTips":["Strip duplicate EXIF segments with exiftool/jpegtran before embedding JPEGs.","If source modification isn't possible, bypass canUseImageDecoder and use JpegImage.parse directly.","Report non-compliant EXIF duplication to the producing tool."],"tags":["jpeg","exif","format-validation","image-decoding"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}