Troubleshooting
What goes wrong when HTML becomes a PDF
Grouped by where in the pipeline it breaks, because that is what narrows it down fastest. The ones under “the document is wrong” are the expensive ones: they do not throw, so nothing tells you about them until someone opens the file.
Several of these come down to a CSS property doing nothing because it is not implemented for paged output. The paged CSS reference says which ones those are. When the renderer will not start at all, and the failure is a package size limit or a missing shared library rather than anything about the document, that is why your PDF renderer will not deploy.
The document is wrong
- Background colours and images are missing from the PDF
Browsers drop backgrounds when printing, because a page with every background painted would empty a toner cartridge, and most render APIs inherit that default.
- The generated PDF is blank
Almost always one of three things: the content is rendered by JavaScript that had not run when the snapshot was taken, the body has no height because everything inside it is absolutely positioned or floated, or the markup you sent was empty because the template call returned before the data arrived..
- Images do not appear in the PDF
The image src is a path rather than a URL.
- The PDF ignores my CSS
The stylesheet is linked rather than embedded, and the link points somewhere the renderer cannot reach: a bundler-generated path, a digested asset filename, or a URL behind your application's authentication.
- Content rendered by JavaScript is missing from the PDF
The snapshot was taken before the script finished.
- The PDF renders the mobile layout instead of the desktop one
The render viewport is narrower than your first breakpoint, so your own media queries are doing exactly what you told them to.
- The PDF comes out in dark mode
prefers-color-scheme resolved to dark in the render environment, and your stylesheet has a dark block.
- Charts and canvas elements are blank in the PDF
A canvas element draws imperatively.
- SVG images are missing or wrong in the PDF
There are three different problems wearing one symptom.
- The generated PDF is far too large
Almost always images at their source resolution.
- Links in the PDF are not clickable
Either the markup styles something to look like a link without being an anchor, or the anchor href is relative.
It paginates wrong
- Page breaks land in the wrong place
Nothing told the layout where it is allowed to break, so it breaks wherever the content runs out of page.
- Table headers do not repeat on the next page
Header repetition is driven by table sectioning, not by styling.
- There is an extra blank page at the end
Something extends a fraction of a millimetre past the end of the last page.
- Content is cut off at the right edge of the page
The element is wider than the page's content box and has nothing telling it to wrap.
- The header and footer do not appear
Header and footer templates are rendered in their own context with none of the document's CSS, and with a default font size of zero in some engines.
- Page numbers are missing or all show 1
Page numbers come from the footer template's special classes, not from CSS counters in the document body.
- The PDF comes out the wrong paper size
Two things can set the page size and they disagree.
- Page margins are ignored in a generated PDF
Same collision as page size: a margin set in the render options and a margin set in an @page rule, with the engine picking one.
- position: fixed elements repeat on every page or vanish
Fixed positioning means fixed to the viewport, and a paged document has one viewport per page or none at all depending on the engine.
- Flexbox and grid layouts break across pages
Break rules apply to items, not to containers, and a flex or grid container that is taller than a page has to break somewhere.
- Single lines are left stranded at the top or bottom of a page
The orphans and widows properties default to a value of 2 in most engines, which is low enough that a single stranded line is still legal in a lot of cases, particularly with short paragraphs.
Text and fonts
- Custom fonts fall back to a default in the PDF
The font file was not fetched.
- Chinese, Japanese or Korean characters show as boxes
The font in use has no glyphs for those characters, and no font on the render machine does either.
- Emoji do not render in the PDF
Emoji need a dedicated font, and colour emoji need one in a colour font format.
- Arabic or Hebrew text renders backwards or disconnected
Two separate problems.
- Text in the PDF cannot be selected or searched
The text is not text.
- Line breaks in the PDF differ from the browser preview
The font is not the same.
- Long words and URLs overflow the page
The default wrapping rules break lines at spaces and a handful of punctuation marks.
It will not run
- Failed to launch the browser process
A headless browser is not a self-contained binary.
- libnss3.so: cannot open shared object file
This is the previous error with the first missing library named.
- Navigation timeout of 30000 ms exceeded
The default wait condition is the network going idle, and something on the page is keeping it busy: an analytics beacon, a font request to a host that is not responding, a polling request, or an ad script.
- Protocol error (Page.printToPDF): Target closed
The tab crashed, and by far the most common reason is memory.
- Chromium does not fit in an AWS Lambda deployment package
A full browser build is several hundred megabytes and the unzipped package limit is 250MB.
- PDF generation runs out of memory
Two multiplying factors.
- Chrome processes accumulate and never exit
A browser launched per request has to be closed, and the close is skipped whenever the render throws before reaching it.
- Renders crash under concurrency in a container
Docker gives a container 64MB of shared memory by default, and a browser uses shared memory heavily for its renderer processes.
- PDF generation is too slow
Usually waiting rather than working.
The request or the response
- The downloaded PDF is corrupted and will not open
The bytes were treated as text somewhere.
- The PDF opens in the browser instead of downloading
Content-Disposition is absent or set to inline.
- 413 Payload Too Large when sending HTML to render
The request body exceeded a limit.
- 401 Unauthorized from the render API
The key that arrived is not the key you think you sent.
- 429 Too Many Requests when generating PDFs in bulk
Unbounded concurrency.
- The PDF is truncated or ends mid-document
The response was cut off.