mozilla/pdf.js · error · XRefEntryException

Bad (compressed) XRef entry: ${ref}

Error message

Bad (compressed) XRef entry: ${ref}

What it means

An XRefEntryException thrown at the end of XRef.fetchCompressed: after building the entries array of length N, the lookup entries[xrefEntry.gen] is undefined. The compressed xref entry's generation field is meant to be the index into the ObjStm's object list; if gen is out of range (>= N) the requested object does not exist in that stream. The full Ref is included in the message.

Source

Thrown at src/core/xref.js:1037

      entries[i] = obj;
      if (obj instanceof BaseStream) {
        continue;
      }
      const num = nums[i],
        entry = this.#entries[num];
      if (entry && entry.offset === tableOffset && entry.gen === i) {
        if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
          assert(
            obj !== undefined,
            'fetchCompressed: The "obj" cannot be undefined.'
          );
        }
        this.#cacheMap.set(num, obj);
      }
    }
    xrefEntry = entries[xrefEntry.gen];
    if (xrefEntry === undefined) {
      throw new XRefEntryException(`Bad (compressed) XRef entry: ${ref}`);
    }
    return xrefEntry;
  }

  async fetchIfRefAsync(obj, suppressEncryption) {
    return obj instanceof Ref ? this.fetchAsync(obj, suppressEncryption) : obj;
  }

  async fetchAsync(ref, suppressEncryption) {
    try {
      return this.fetch(ref, suppressEncryption);
    } catch (ex) {
      if (!(ex instanceof MissingDataException)) {
        throw ex;
      }
      await this.pdfManager.requestRange(ex.begin, ex.end);
      return this.fetchAsync(ref, suppressEncryption);
    }

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Repair with qpdf --check / mutool clean to rebuild the cross-reference.
  2. Re-export the PDF.
  3. Catch XRefEntryException at the page-access boundary and skip the affected object/page.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const page = await doc.getPage(n);
} catch (e) {
  // XRefEntryException is not always exported; match by name.
  if (e.name === 'XRefEntryException' || /Bad \(compressed\) XRef entry/.test(e.message)) {
    console.warn(`Page ${n} unavailable: bad compressed xref entry`);
    continue;
  }
  throw e;
}

Prevention

When it happens

Trigger: A compressed xref entry whose generation index points past the end of the ObjStm object list; /N undercount relative to the entry's index; a corrupted generation value; a stream that was rewritten with fewer objects than the xref expects.

Common situations: Inconsistent xref vs object stream after a botched incremental update; buggy writers; files edited by hand or by non-conformant tools.

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/07ee0f258854c867. Report an issue: GitHub.