{"record":{"id":"c39b69302eaf8023","repo":"mozilla/pdf.js","slug":"invalid-offset-in-the-objstm-stream","errorCode":null,"errorMessage":"Invalid offset in the ObjStm stream.","messagePattern":"Invalid offset in the ObjStm stream\\.","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/xref.js","lineNumber":1008,"sourceCode":"\n      // The entry in the xref table is the object number followed by the index.\n      // So if index (gen number) is not the same as the index (i), we fix it\n      // (fixes bug 1978317).\n      const entry = this.getEntry(num);\n      if (entry?.offset === tableOffset && entry.gen !== i) {\n        entry.gen = i;\n      }\n\n      offsets[i] = offset;\n    }\n\n    const start = (stream.start || 0) + first;\n    const entries = new Array(n);\n    // read stream objects for cache\n    for (let i = 0; i < n; ++i) {\n      const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined;\n      if (length < 0) {\n        throw new FormatError(\"Invalid offset in the ObjStm stream.\");\n      }\n      parser = new Parser({\n        lexer: new Lexer(\n          stream.makeSubStream(start + offsets[i], length, stream.dict)\n        ),\n        xref: this,\n        allowStreams: true,\n      });\n\n      const obj = parser.getObj();\n      entries[i] = obj;\n      if (obj instanceof BaseStream) {\n        continue;\n      }\n      const num = nums[i],\n        entry = this.#entries[num];\n      if (entry && entry.offset === tableOffset && entry.gen === i) {\n        if (typeof PDFJSDev === \"undefined\" || PDFJSDev.test(\"TESTING\")) {","sourceCodeStart":990,"sourceCodeEnd":1026,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/xref.js#L990-L1026","documentation":"A FormatError raised in the second ObjStm pass: when slicing the stream into per-object sub-streams, offset[i+1] - offset[i] is negative, meaning the recorded offsets are not monotonically increasing. pdf.js computes each object's byte length from consecutive offsets; a negative length is impossible and the stream is internally inconsistent.","triggerScenarios":"An ObjStm where the offset table is out of order (offset[i+1] < offset[i]); a writer that emitted offsets in a different order than the objects; decryption corruption that scrambled the offset values.","commonSituations":"Faulty generators, repaired-but-inconsistent files, partially overwritten object streams.","solutions":["Repair the PDF with qpdf --check / mutool clean to rebuild the object stream with sorted offsets.","Re-export the source document.","Catch FormatError around the failing page and continue with other pages."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await doc.getPage(n);\n} catch (e) {\n  if (e instanceof pdfjsLib.FormatError) { /* skip page */ }\n}","preventionTips":["Use qpdf --check / mutool clean to rebuild object streams before loading.","Catch FormatError per page to keep the rest of the document usable."],"tags":["objstm","corruption","format-error","offsets"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}