Skip to content

getTextContent drops all page text ("Cannot read properties of null (reading 'name')") when the first text in a stream has font size 0 #22381

Closed

Description

@zhaodengfeng

Attach (recommended) or Link to PDF file

The file is plain text, 613 bytes. Save it as zero-size-text.pdf (keep LF line endings, since the xref offsets depend on them):

%PDF-1.4
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj
2 0 obj
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
endobj
3 0 obj
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 300 144] /Resources << /Font << /F1 5 0 R >> >> /Contents 4 0 R >>
endobj
4 0 obj
<< /Length 69 >>
stream
BT /F1 0 Tf (hidden) Tj ET
BT /F1 24 Tf 36 60 Td (Visible text) Tj ET
endstream
endobj
5 0 obj
<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>
endobj
xref
0 6
0000000000 65535 f 
0000000009 00000 n 
0000000058 00000 n 
0000000115 00000 n 
0000000241 00000 n 
0000000360 00000 n 
trailer
<< /Size 6 /Root 1 0 R >>
startxref
430
%%EOF

Real-world files that hit this are broker research PDFs processed by Aspose.PDF for .NET 19.10. Aspose adds an invisible watermark artifact: a form XObject that begins with BT /F0 0 Tf 1 1 1 rg ... (<base64>) Tj ET before any other text. I can't share those files, but the minimal file above reproduces the same failure.

Web browser and its version

Not browser-specific. Reproduced in Node.js 24.22.1 with pdfjs-dist/legacy/build/pdf.mjs.

Operating system and its version

macOS 26

PDF.js version

6.4.299 (also 5.7.284)

Is the bug present in the latest PDF.js version?

Yes. The code path is unchanged on master (87b369c).

Is a browser extension

No

Steps to reproduce the problem

import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
import fs from "node:fs";

const data = new Uint8Array(fs.readFileSync("zero-size-text.pdf"));

// Default options: the error is swallowed and the page loses all its text.
let doc = await getDocument({ data }).promise;
console.log((await (await doc.getPage(1)).getTextContent()).items.map(i => i.str));
// Warning: getTextContent - ignoring errors during "GetTextContent: page 0" task:
//   "TypeError: Cannot read properties of null (reading 'name')".
// []

// stopAtErrors: true: the call rejects.
doc = await getDocument({ data, stopAtErrors: true }).promise;
await (await doc.getPage(1)).getTextContent();
// TypeError: Cannot read properties of null (reading 'name')

What is the expected behavior?

items contains "Visible text", and probably also the empty or size-0 "hidden" run. MuPDF extracts Visible text from this page. Rendering (getOperatorList) works fine in PDF.js too.

What went wrong?

In buildTextContentItem (src/core/evaluator.js):

if (
  currentTextState !== textState &&
  (currentTextState.fontSize !== textState.fontSize ||
    (currentTextState.fontName !== textState.fontName &&
      (currentTextState.font.name !== textState.font.name ||
        currentTextState.font.vertical !== textState.font.vertical)))
) {

currentTextState is cloned from the initial text state, before any Tf is applied, so its font is null and its fontSize is 0. When the first text in the stream is shown at size 0, the fontSize comparison is equal. Evaluation then falls through to currentTextState.font.name and throws. With the default ignoreErrors, the rest of the page's text is discarded, not just the hidden run.

Any non-zero first size (for example BT /F1 8 Tf (x) Tj ET) works, because the fontSize comparison short-circuits. Optional chaining (currentTextState.font?.name, currentTextState.font?.vertical) fixes it. With that change, 343 real-world PDFs that I had (90 failing pages) all extract without error.

Link to a viewer

No response

Additional context

Found through a downstream tool that inspects generated PDFs with getTextContent (makecindy/cindy#7890). That PR works around the bug by catching the error per page.

Activity

  1. Snuffleupagus commented on Oct 29, 2026

    @Snuffleupagus
    Collaborator

    The file is plain text, 613 bytes. Save it as zero-size-text.pdf (keep LF line endings, since the xref offsets depend on them):

    Attach the actual PDF file, rather than forcing people to manually having to re-create it.

  2. yograj-vijay-yadav commented on Oct 29, 2026

    @yograj-vijay-yadav
  3. zhaodengfeng commented on Oct 29, 2026

    @zhaodengfeng
    Author

    Sorry about that. I already have a fix with a unit test, and I'm opening a PR shortly. It adds the PDF as test/pdfs/ reference file, so it will be attached there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions