{"record":{"id":"5be312ef0c7a5c51","repo":"mozilla/pdf.js","slug":"bad-objstm-stream","errorCode":null,"errorMessage":"bad ObjStm stream","messagePattern":"bad ObjStm stream","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/xref.js","lineNumber":961,"sourceCode":"        ? parser.getObj(this.encrypt.createCipherTransform(num, gen))\n        : parser.getObj();\n    if (!(xrefEntry instanceof BaseStream)) {\n      if (typeof PDFJSDev === \"undefined\" || PDFJSDev.test(\"TESTING\")) {\n        assert(\n          xrefEntry !== undefined,\n          'fetchUncompressed: The \"xrefEntry\" cannot be undefined.'\n        );\n      }\n      this.#cacheMap.set(num, xrefEntry);\n    }\n    return xrefEntry;\n  }\n\n  fetchCompressed(ref, xrefEntry, suppressEncryption = false) {\n    const tableOffset = xrefEntry.offset;\n    const stream = this.fetch(Ref.get(tableOffset, 0));\n    if (!(stream instanceof BaseStream)) {\n      throw new FormatError(\"bad ObjStm stream\");\n    }\n    const first = stream.dict.get(\"First\");\n    const n = stream.dict.get(\"N\");\n    if (!Number.isInteger(first) || !Number.isInteger(n)) {\n      throw new FormatError(\"invalid first and n parameters for ObjStm stream\");\n    }\n    let parser = new Parser({\n      lexer: new Lexer(stream),\n      xref: this,\n      allowStreams: true,\n    });\n    const nums = new Array(n);\n    const offsets = new Array(n);\n    // read the object numbers to populate cache\n    for (let i = 0; i < n; ++i) {\n      const num = parser.getObj();\n      if (!Number.isInteger(num)) {\n        throw new FormatError(","sourceCodeStart":943,"sourceCodeEnd":979,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/xref.js#L943-L979","documentation":"A FormatError raised in XRef.fetchCompressed when the object referenced by a compressed xref entry does not resolve to a BaseStream. Object Streams (ObjStm) must be streams; if the fetch returns a plain dict, null, or a primitive, the compressed object cannot be decoded. It indicates the xref entry's offset points at the wrong object or the object stream itself is malformed.","triggerScenarios":"A compressed xref table entry whose offset field references an object number that is not an ObjStm; a cross-reference where the generator object was overwritten/corrupted; encrypted ObjStm decrypted to a non-stream; manual xref edits that point at the wrong object.","commonSituations":"PDFs produced by buggy/minimal writers; files repaired by tools that rewrote the xref incorrectly; files damaged in transit that still have a readable trailer but a broken object stream.","solutions":["Validate the file with qpdf --check or mutool clean to detect/repair object stream corruption.","Re-export the PDF from its source application.","Catch FormatError around page access and skip the affected page rather than failing the whole document.","If generating PDFs yourself, ensure ObjStm objects are emitted as streams with correct /Type /ObjStm."],"exampleFix":"// before\nconst page = await doc.getPage(n);\nconst content = await page.getTextContent(); // throws FormatError\n\n// after\ntry {\n  const page = await doc.getPage(n);\n  const content = await page.getTextContent();\n} catch (e) {\n  if (e instanceof pdfjsLib.FormatError) {\n  console.warn(`Page ${n} skipped: corrupt object stream`, e.message);\n  }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const obj = await doc.getPage(n);\n} catch (e) {\n  if (e instanceof pdfjsLib.FormatError) {\n    console.warn(`Skipping object/page ${n}: corrupt ObjStm`);\n    continue;\n  }\n  throw e;\n}","preventionTips":["Run qpdf --check on uploaded PDFs before processing.","Isolate per-page access in try/catch so one bad object stream does not kill the whole document.","Keep worker and API builds on the same version."],"tags":["objstm","compression","xref","corruption","format-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}