Troubleshooting: fonts, subsetting, and tagging
These entries cover font resolution and parsing failures raised through
NextPDF\Exception\FontNotFoundException and
NextPDF\Exception\FontParsingException. They also cover Chinese, Japanese,
and Korean (CJK) coverage diagnostics and structure-tree issues that affect
tagged output. Each entry names the exact exception or test so you can verify
the cause.
Entry: font not found
Section titled “Entry: font not found”- Symptom.
FontNotFoundExceptionwith a message of the formFont "<name>" not found. Searched: [<paths>]. - Likely cause. The requested font family or file path does not exist, is not readable, or lives in a fonts directory the runtime cannot access. The font data may be valid, but the engine still cannot reach it.
- Evidence / diagnosis.
getContext()returnsfont_name,search_paths, andfallback_attempted. Usesearch_pathsto review every location the engine tried. Usefallback_attemptedto confirm whether a fallback already ran. - Resolution.
- Compare the requested
font_namewith the font file that is actually present. - Add the directory that contains the font to the configured fonts directory, or correct the path you passed.
- Verify that the runtime user can read the file.
- Re-run the call.
- Compare the requested
- Related. Exception reference.
Entry: font file fails to parse
Section titled “Entry: font file fails to parse”- Symptom.
FontParsingExceptionwith a message of the formFailed to parse font file "<file>": <reason>. - Likely cause. The engine found the font file, but cannot use its
contents: a truncated header, an invalid table directory, or a missing
mandatory table such as
head,hhea, orOS/2. - Evidence / diagnosis.
getContext()returnsfont_fileandparse_error.parse_errornames the structural problem. - Resolution.
- Read
parse_errorto identify the structural defect. - Replace the font file with a known-good copy of the same face.
- Re-run the call.
- Read
- Related. Exception reference.
Entry: subsetting fails on a malformed font table
Section titled “Entry: subsetting fails on a malformed font table”- Symptom.
FontParsingExceptionwith afont_filevalue offont-subsetand aparse_errorsuch asInvalid head table: too short,Invalid hhea table: too short,Invalid maxp table: too short, orFailed to unpack font data. - Likely cause. The font passed initial loading, but a table needed for subsetting is truncated or cannot be unpacked. The subsetter rejects the font instead of emitting a broken subset.
- Evidence / diagnosis. When a
head,hhea, ormaxptable is too short or an unpack fails,src/Typography/FontSubsetter.phpraisesFontParsingExceptionwith the literal tokenfont-subsetas the file name. The token tells you the failure happened during subsetting, not initial loading. - Resolution.
- Replace the source font with a complete, non-truncated copy of the same face.
- If a build tool generates the font, regenerate it and verify that the
head,hhea, andmaxptables are complete. - Re-run the build.
- Related. PDF/A and PDF/UA validation.
Entry: CJK text renders with missing glyphs
Section titled “Entry: CJK text renders with missing glyphs”- Symptom. Chinese, Japanese, or Korean text renders as blank boxes or missing characters, and the font’s CJK coverage is uncertain.
- Likely cause. The selected font does not cover the Unicode blocks the script requires. Each CJK script requires specific blocks in addition to the shared ideograph blocks.
- Evidence / diagnosis.
src/Typography/CjkFontValidator.phpprovidesvalidateCoverage(FontInfo $font, CjkScript $script). It returns aCjkCoverageResultwith the coverage percentage and any blocks below the 50% reporting threshold. The validator samples codepoints. It is a diagnostic and does not modify font loading. - Resolution.
- Run
CjkFontValidator::validateCoverage()for the font and the target script. - Read the
missingRangesto see which blocks are uncovered, for example, Bopomofo for Traditional Chinese, Hiragana and Katakana for Japanese, and Hangul Syllables for Korean. - Select a font that covers those blocks, or add a fallback font that does.
- Re-run rendering and re-check coverage.
- Run
- Related. Exception reference.
Entry: predefined CMap does not match the CJK script
Section titled “Entry: predefined CMap does not match the CJK script”- Symptom. CJK text maps to the wrong glyphs, or the document uses a predefined CMap that does not match its language.
- Likely cause. The detected script determines the Adobe predefined CMap name. A font that covers only the shared ideograph block, with no script-specific block, is detected as Simplified Chinese by design.
- Evidence / diagnosis.
CjkFontValidator::detectScript()returns the detected script, andresolvePredefinedCMapName()maps it: Simplified Chinese toUniGB-UTF16-H, Traditional Chinese toUniCNS-UTF16-H, Japanese toUniJIS-UTF16-H, and Korean toUniKS-UTF16-H. If no script-specific block is present, detection falls back to Simplified Chinese. - Resolution.
- Confirm that the font ships the script-specific block: Bopomofo for Traditional Chinese, Hiragana or Katakana for Japanese, and Hangul for Korean.
- If the document is Traditional Chinese but the font has no Bopomofo block, select a font that includes one so detection resolves to the intended script.
- Re-run rendering.
- Related. Exception reference.
Entry: tagged content does not produce a usable structure tree
Section titled “Entry: tagged content does not produce a usable structure tree”- Symptom. A tagged build produces no structure, or a downstream accessibility check reports an empty or missing structure tree.
- Likely cause. The build emitted content outside the tagging path, so it created no structure elements. The structure tree stays empty.
- Evidence / diagnosis.
src/Accessibility/StructureTree.phpandsrc/Accessibility/TaggedContentEmitter.phpbuild the structure tree from tagged content. The testtests/Integration/Accessibility/EmptyTaggedPdfDoesNotAdvertisePdfUa2Test.phpconfirms that an empty structure tree does not advertise PDF/UA-2. - Resolution.
- Confirm content is emitted through the tagging path so structure elements are created.
- Verify each marked-content sequence maps to a structure element.
- Re-run the build and inspect the structure tree.
- Related. PDF/A and PDF/UA validation.
Entry: structure-element language tag is rejected
Section titled “Entry: structure-element language tag is rejected”- Symptom. A build fails because a language value on a structure element or on the document is not a valid tag.
- Likely cause. The supplied language is not a valid BCP 47 tag. The validator rejects malformed tags instead of emitting them.
- Evidence / diagnosis.
src/Accessibility/Bcp47Validator.phpvalidates the tag. An invalid tag raisessrc/Accessibility/InvalidBcp47TagException.php.tests/Unit/Conformance/PdfUa2Section844LangStrictTest.phpexercises the strict PDF/UA-2 language requirement. - Resolution.
- Replace the language value with a valid BCP 47 tag, such as
en-US,de-DE, orzh-Hant-TW. - Set the language on the specific structure element when a passage differs from the document language.
- Re-run the build.
- Replace the language value with a valid BCP 47 tag, such as
- Related. PDF/A and PDF/UA validation.
Edge cases & gotchas
Section titled “Edge cases & gotchas”FontNotFoundExceptionandFontParsingExceptionreport different failures. Not-found means the file could not be reached. Parsing means the file was reached, but its bytes are not usable. Read the class to identify which failure occurred.font-subsetinfont_fileis a deliberate marker for the subsetting stage, not an actual path. Do not look for a file namedfont-subset.CjkFontValidatorsamples codepoints rather than checking every one, so its coverage figure is a font-selection estimate, not a byte-exact audit.- An empty structure tree is reported as not PDF/UA-2 by design. This is the documented engine behavior, not a defect.
See also
Section titled “See also”Glossary: font subsetting · CJK coverage · structure tree