Skip to content

Troubleshooting

Text renders as boxes or blanks

The font does not contain glyphs for those characters. The standard 14 fonts only cover WinAnsi (Latin-1), so anything beyond that needs an embedded font:

js
const font = await pdfDoc.embedFont(
  fs.readFileSync('NotoSansKhmer-Regular.ttf'),
);

If an embedded font still shows blanks, it genuinely lacks those glyphs — Noto Sans does not cover Khmer, for instance; you need Noto Sans Khmer.

WinAnsi cannot encode error

Thrown when non-Latin text is drawn with a standard font. Embed a font that covers the script.

Field appearances throw when a form is filled

Field appearances are generated with a font, and it must support the text:

js
const khmer = await pdfDoc.embedFont(khmerBytes);
form.getTextField('name').setText('សុខា');
form.updateFieldAppearances(khmer);

Variable font ignores my variations

Values are clamped to the axis range in the font's fvar table. A font whose wght runs 400–700 treats { wght: 100 } as 400 — silently. Check the axis ranges before assuming the request was honoured.

Output differs between runs

Documents get creation and modification dates by default. For byte-identical output:

js
const pdfDoc = await PDFDocument.create({ updateMetadata: false });

Files are large

Subset the fonts:

js
const font = await pdfDoc.embedFont(bytes, { subset: true });

A full CJK or variable font can be several megabytes; a subset is usually tens of kilobytes. Also make sure a repeatedly-drawn image is embedded once and reused rather than embedded per use.

Text is positioned oddly after upgrading

HappyPDF writes one positioned glyph per operator instead of one string per line, so the content stream differs from pdf-lib's. The rendering is equivalent, but code that parses your own output, or compares content streams, will see different operators.

Intl.Segmenter is not a function

The runtime is too old. HappyPDF requires Node 22+, or a browser from 2022 onward.

Loading an encrypted PDF fails

js
const pdfDoc = await PDFDocument.load(bytes, { password: 'secret' });

Without the password, EncryptedPDFError is thrown. ignoreEncryption: true lets you inspect the structure, but the content will be ciphertext.

Getting help

Open an issue at github.com/seanghay/happypdf/issues. A minimal snippet and, where possible, the font you used make problems far easier to reproduce.

MIT Licensed. A fork of pdf-lib.