Ask Anvil

Answers to questions about automating PDFs, e-signatures, Webforms, and other paperwork problems.
PDFs
Categories

Why does long text get cut off in my generated PDF, and how do I fix it?

Your template passes review with test data. Then a real record arrives with a 70-character company name, and the field on the finished PDF reads "Acme Manufacturing and Di". Nothing throws. The fill returns success, the file downloads, and most of the value is quietly gone.

Check the stored value first

Read the field back after filling. If the whole string is still there, your data layer is fine and the problem is purely visual, which narrows the search considerably.

const doc = await PDFDocument.load(fs.readFileSync('filled.pdf'))
const field = doc.getForm().getTextField('employerName')

console.log(field.getText().length) // 70, the full value is intact

A text field keeps its value separately from the appearance stream that actually gets painted on the page. The value survives intact. The drawing is what gets clipped, which is why the truncation never shows up as an error anywhere in your pipeline.

Why the drawing gets clipped

A PDF text field is a fixed rectangle. By default the value is drawn on a single line, and the generated appearance stream sets a clipping path to that rectangle, so any glyphs past the right edge are simply never painted.

The font size makes this worse than people expect. Fill a 200 by 22 point field with pdf-lib and it writes the text at 17 point, sized against the height of the field rather than the width of your string. That 70-character company name needs 544 points at 17 point Helvetica, against roughly 197 points of usable clip width, so you see about a third of it.

The fix for form fields

import { PDFDocument, StandardFonts } from 'pdf-lib'
import fs from 'node:fs'

const doc = await PDFDocument.load(fs.readFileSync('template.pdf'))
const form = doc.getForm()
const field = form.getTextField('employerName')

field.enableMultiline() // wrap instead of clipping at the right edge

try {
  field.setFontSize(8) // throws if the field has no /DA font size
} catch {
  // leave the size alone and let the default appearance stand
}

field.setText('Acme Manufacturing and Distribution Holdings, LLC (Northeast Division)')

const helvetica = await doc.embedFont(StandardFonts.Helvetica)
form.updateFieldAppearances(helvetica)
fs.writeFileSync('filled.pdf', await doc.save())

In pdf-lib's own words, enableMultiline makes the field "display each line of text on a new line," and setFontSize gives those wrapped lines room to fit. Keep setFontSize inside a try block: the docs are explicit that it throws if the field has no default appearance string, or if that string contains no font size, which is common in third-party forms you did not author. With those two calls the same value renders across two lines instead of one clipped one.

If you are rendering HTML to PDF instead

Same symptom, different cause. Look for a container with a fixed height plus overflow: hidden. Per the CSS spec, hidden clips overflowing content at the element's padding box with no scroll bar, so nothing on the page hints that anything is missing. Drop the fixed height from anything holding variable-length data and let the block grow. For values that can arrive as one long unbroken string, such as an email address or an account number, add overflow-wrap: anywhere, which lets an otherwise unbreakable string break at any point rather than push past the box.

The step people skip

Test with your longest real value, not "John Smith". Query the maximum length of every column you merge into the template and render a fixture from those values. Truncation here is silent by design, so a max-length fixture in your test suite is the only thing that reliably catches it before a customer does.

Back to All Questions

The fastest way to build software for documents

Anvil Document SDK is a comprehensive toolbox for product teams launching document flows where PDF filling, signing, and complex conditional scenarios are necessary.
Explore Anvil
Anvil Webforms