Skip to content

unsupported number: …e+21 on long documents with a fixed page-number element, lineHeight is multiplied by fontSize on every pagination pass #3452

Description

@Dot-47

Describe the bug
Rendering a document of roughly 10+ pages that contains the standard page-number recipe from the docs (a fixed <Text> with a render callback) crashes with:

Error: unsupported number: -1.0625324586456702e+22
    at PDFObject.number (pdfkit)
    at PDFDocument.translate
    at renderText (@react-pdf/render)

Shorter documents render without error, so it seems random. The same problem is happening, but it just stays below pdfkit's 10²¹ coordinate limit.

This is the likely cause behind #3277 and related to #2988 and it seems the PR #3337 only clamps the out-of-range number in pdfkit, but the underlying value problem remains.

To Reproduce
Done with @react-pdf/renderer primitives only, plain text.

import { Document, Page, Text, pdf } from "@react-pdf/renderer";

const paragraphs = 400;

const element = (
	<Document>
		<Page size="A4" style={{ padding: 56, fontSize: 12, lineHeight: 1.5 }}>
			<Text
				fixed
				style={{ position: "absolute", bottom: 24, left: 0, right: 0, textAlign: "center", fontSize: 8 }}
				render={({ pageNumber, totalPages }) => `${pageNumber} / ${totalPages}`}
			/>

			{Array.from({ length: paragraphs }, (_, i) => (
				<Text key={i}>
					Paragraph {i}: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. (some test to fill the pages and generate some pagination).
				</Text>
			))}
		</Page>
	</Document>
);

// Error: unsupported number: -1.06…e+22
await pdf(element).toBlob(); 

If you reduce paragraphs to a small number (less pages), the error disappears.
If you remove the footer with the render(), the error disappears.
If you remove the lineHeight, also works

Expected behavior
The amount of pages should not cause a crash like this.

Suspected Issue / Suggested Fix
The problem seems to be with resolvePageStyles and transformLineHeight not being idempotent. It seems to resolve lineHeight x font-size, which is a unitless number, and keeps looping.

I don't know the code well enough to propose a fix, but it seems making the re-resolution idempotent could resolve this problem. resolveNodeStyles should either resolve from the original props.style instead of the newly resolved node.style or just skip any nodes that have already resolved styles. I did a test run where I tagged the resolved style objects with a flag and that fixed the problem for later passes without any crash or visual regression.

Desktop (please complete the following information):

  • OS: Ubuntu & Windows 10
  • Browser: Firefox
  • React-pdf version: @react-pdf/renderer: ^4.5.1 (latest), @react-pdf/layout: ^4.6.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions