Matterhorn 31-011 · PDF/UA-1 UA1:7.21.4.1-3
Font subset missing a glyph the text still uses
The subset embedded in the file is missing glyphs the content stream asks for — very common when a document is edited after subsetting.
The condition, as the protocol states it. “For a font used by text the font program is embedded but it does not contain glyphs for all of the glyphs referenced by the text used for rendering.”
Matterhorn Protocol 1.1, checkpoint 31, index 31-011, section UA1:7.21.4.1-3. Software can decide this one on its own.
What a screen reader actually does
The viewer draws a blank or a box where the missing glyph should be. What a screen reader hears comes from the ToUnicode map, not the glyph — often the character the page fails to show, or nothing if the map was not updated either.
What the condition is
Most PDFs embed a subset: only the glyphs the document uses, under a name with a six-letter tag such as ABCDEF+Calibri. That keeps files small, and it works as long as the subset is built from the text it will have to draw.
This condition is a font whose embedded program does not contain a glyph that the text asks for. In the file Taggart’s test suite uses for this page, the font is a CID font with an Identity CIDToGIDMap, so each two-byte code is simply a glyph index:
BT /F1 36 Tf 40 40 Td <0001 0002 0003 0004> Tj ET
/DescendantFonts [ << /Subtype /CIDFontType2
/BaseFont /JBATCH+Subset
/CIDToGIDMap /Identity
/FontDescriptor << /FontFile2 … >> >> ]
The embedded program holds four glyphs, numbered 0 to 3. The text asks for glyph 4. For a simple font the route is longer — code, then encoding, then glyph name, then glyph — but the failure is the same: the last step lands on nothing.
What breaks, and what a screen-reader user hears
The viewer draws the font’s .notdef glyph instead, which in most fonts is an empty rectangle or nothing at all. Poppler renders the test file as three boxes and a blank where the fourth should be.
What a screen reader gets is a separate question, because extraction never consults the glyph. It goes from the code to Unicode through the ToUnicode CMap, and in the test file that map is complete: pdftotext returns ABCD. The screen-reader user hears four letters; the sighted reader sees three and a gap. Neither has any reason to suspect the other is getting something different.
Whether the missing character is also unreadable depends on how the file got this way. When text is edited after the font was subset, the ToUnicode map is often left as it was too, and then the code reaches no character either — that is 10-001, and the reader hears nothing where the gap is.
Where it comes from
Text edited after the font was subset. An editor that changes or adds text and reuses the existing subset, rather than re-embedding the font with the new characters, produces exactly the test file: codes that point past the end of the program.
Merged or optimised files. Two documents carrying different subsets of the same font can end up sharing one, if a tool that merges or slims files treats them as the same font. The subset tag exists to keep them apart, but only a tool that respects it is protected by it.
Form fields. A field whose appearance is drawn in an embedded subset can only show the characters that subset has. A value typed later that needs another glyph runs into this condition.
How to check it free
Look, then copy. A box or a blank where a character should be is the visible half. Copy that line and paste it into a plain text editor: if the paste contains a character the page does not show, the glyph is missing from the program and the mapping is not.
veraPDF tests this under clause 7.21.4.1, one glyph at a time, and leaves out text in rendering mode 3.
Acrobat Pro’s Preflight inventory shows what is actually in each embedded font. Select Use print production → Preflight from the All tools menu, then Options → Create Inventory. Adobe’s page on Preflight reports says the inventory shows which glyphs in a font are embedded, what they look like and which character they are supposed to represent, and suggests it for exactly this — resolving a missing-glyph error. To look at a single font’s glyphs in detail, the advanced inspections page describes Options → Browse Internal Structure of All Document Fonts.
pdffonts from Poppler is less help here than usual: its sub column tells you a font is a subset, not what the subset lacks.
How to fix it free
Re-export from the source document. The subset is then built from the text as it now stands, with the font installed, and every glyph the page uses is in it. This is the only fix that works in general.
Acrobat cannot add glyphs to an embedded subset. Adobe’s font browser is read-only — its page says you can navigate the fonts but cannot edit them — and none of the Preflight fixups Adobe documents replaces a subset with a fuller one.
If the text was edited in a PDF editor, the edit is what broke it, so make the change in the source instead, or redo it in a tool that re-embeds the font rather than reusing the subset.
For form fields, the fix is in whatever built the form: the font a field draws its value in has to carry every glyph a person might type, which in practice means not subsetting it.
What Taggart does
Taggart does not detect this condition. It does not open embedded font programs: it reads the font dictionaries and the content streams, so it knows which codes each font is used with — that is how it finds codes missing from a ToUnicode CMap — but it does not know which glyphs the program contains.
On the test file it reports nothing about the font at all. What it does instead is refuse to vouch for it: 31-011 is on the list of conditions Taggart does not check, and its conformance statement stops short of a PDF/UA claim — and the identifier is not written into the file — until a person confirms them. In the app that is a checkbox, I have checked these conditions by hand, or with another validator. For this one, veraPDF or the Preflight inventory above is how to earn the tick.
How Taggart handles it
Software could decide this one, and Taggart does not check it yet. A clean report from Taggart says nothing about it either way. It is on the list of conditions Taggart asks you to confirm before it writes the PDF/UA claim into the file; check it by hand or with another validator, as described above.
Whatever Taggart changes, the page still looks identical. Fixes edit the PDF object model, not the content streams, and every remediation is re-rendered and compared against the original at structural similarity ≥ 0.999 before you get the file back. A tool that quietly reflows your document is worse than no tool.
Frequently asked questions
Why does the text copy correctly when the page shows a gap?
Because copying never looks at the glyph. Extraction goes from the character code to Unicode through the ToUnicode CMap or the encoding; drawing goes from the same code to a glyph in the font program. A file can have the first route intact and the second broken, and then the clipboard holds a letter the page does not show.
Is every box or blank in a PDF a missing glyph?
No. The box is the font's .notdef glyph, and a viewer draws it whenever a lookup fails: the glyph is not in the program (this condition), it is in the program but unreachable through the cmap (31-018), or the font was never embedded and the substitute lacks it (31-009). Acrobat's Preflight inventory shows which glyphs a font actually holds, which tells the three apart.
Can a subset be completed after the fact?
Only by embedding a program that has the glyph, and it has to be the same font at the same version, or the widths in the font dictionary stop matching (31-016). In practice that means re-exporting from the source, where the font is installed and the subset is built from the final text.
Does invisible text count?
No. The requirement is about glyphs referenced for rendering. Text in rendering mode 3, which is how an OCR layer sits invisibly over a scan, draws nothing, so its font does not need the glyphs.
Where this sits in the standards
| Standard | Reference |
|---|---|
| Matterhorn Protocol 1.1 | Checkpoint 31 (Fonts), index 31-011 |
| PDF/UA-1 (ISO 14289-1) | Clause 7.21.4.1-3 |
| WCAG 2.1 | 1.3.1 Info and Relationships — Level A |
| EN 301 549 / Section 508 / ADA Title II | All three point at WCAG 2.1 Level AA for non-web documents, so a Level A or AA criterion here is in scope for each of them. |
Related conditions
- 31-030 Characters used in text showing operators reference the .notdef glyphThe content stream paints glyph index 0, which is by definition "no glyph" — typically a hollow box or nothing at all.
- 31-009 For a font used by text intended to be rendered the font program is not embeddedPDF/UA-1 requires every font used for visible text to be embedded, so the document renders and extracts identically everywhere. A glyph counts as rendered if the text render mode is not 3.
- 10-001 Character code cannot be mapped to UnicodeA glyph is painted whose character code has no Unicode equivalent reachable through the font's ToUnicode CMap, encoding, or glyph names. The text renders correctly but cannot be extracted.
- 31-015 A glyph listed in CIDSet is not present in the CID font programCIDSet promises CIDs the font does not contain.
Other conditions in checkpoint 31
Checkpoint 31 covers fonts. These are its other failure conditions; the ones without a link are in the rule set but do not have a written page yet.
- 31-001 CIDSystemInfo Registry values are not identicalThe CMap and the descendant CID font must agree on the character collection registry.
- 31-002 CIDSystemInfo Ordering values are not identicalThe CMap and the descendant CID font must agree on the character collection ordering.
- 31-003 CIDSystemInfo Supplement of the CID font is lower than that of the CMapThe font's character collection supplement must be at least as new as the CMap's, or the CMap may reference CIDs the font does not define.
- 31-004 A Type 2 CID font contains neither a stream nor the name Identity as CIDToGIDMapCIDToGIDMap must be either the name /Identity or a stream mapping CIDs to glyph indices.
- 31-005 A Type 2 CID font does not contain a CIDToGIDMap entryThe entry is absent entirely.
- 31-006 A CMap is neither listed in ISO 32000-1 Table 118 nor embeddedA predefined CMap must be one of the standard names; anything else must be embedded in the file.
- 31-007 The WMode entry in a CMap dictionary is not identical to the WMode value in the CMap streamWriting mode (horizontal or vertical) must be declared consistently in the dictionary and the stream.
- 31-008 A CMap references another CMap which is not listed in ISO 32000-1 Table 118A UseCMap chain must terminate at a predefined CMap.
- 31-009 For a font used by text intended to be rendered the font program is not embeddedPDF/UA-1 requires every font used for visible text to be embedded, so the document renders and extracts identically everywhere. A glyph counts as rendered if the text render mode is not 3.
- 31-010 A font program is embedded that is not legally embeddable for unlimited, universal renderingThe font's embedding permission bits forbid the kind of embedding used. Machines can read the flags but the flags may not reflect the actual licence.
- 31-012 A glyph present in an embedded Type 1 font program is not listed in CharSetCharSet must accurately list the glyphs in the embedded subset.
- 31-013 A glyph listed in CharSet is not present in the Type 1 font programCharSet promises glyphs the font does not contain.
- 31-014 A glyph present in an embedded CID font program is not listed in CIDSetCIDSet must accurately list the CIDs in the embedded subset.
- 31-015 A glyph listed in CIDSet is not present in the CID font programCIDSet promises CIDs the font does not contain.
- 31-016 Glyph widths in the font dictionary and the font program differThe /Widths array must agree with the embedded font program.
- 31-017 A non-symbolic TrueType font has no non-symbolic cmapA font declared non-symbolic must actually carry a (3,1) or (1,0) cmap subtable.
- 31-018 A glyph cannot be looked up by any non-symbolic cmap entrySome rendered glyph is unreachable through the declared cmap tables.
- 31-019 The font dictionary for a non-symbolic TrueType font does not contain an Encoding entryNon-symbolic TrueType fonts must declare an /Encoding.
- 31-020 The Encoding dictionary for a non-symbolic TrueType font does not contain BaseEncodingIf /Encoding is a dictionary it must name a /BaseEncoding.
- 31-021 BaseEncoding is neither MacRomanEncoding nor WinAnsiEncodingOnly MacRomanEncoding and WinAnsiEncoding are permitted for non-symbolic TrueType fonts.
- 31-022 Differences contains glyph names not listed in the Adobe Glyph ListGlyph names in /Differences must be resolvable through the Adobe Glyph List so a processor can derive Unicode.
- 31-023 Differences present but the font has no (3,1) Microsoft Unicode cmapThe Differences array is resolved through the (3,1) cmap; without it the mapping is undefined.
- 31-024 The Encoding entry is present in the font dictionary for a symbolic TrueType fontSymbolic TrueType fonts must not carry an /Encoding; the font's own cmap governs.
- 31-025 The embedded font program for a symbolic TrueType font contains no cmapA symbolic TrueType font must contain at least one cmap subtable.
- 31-026 A symbolic TrueType font has multiple cmaps but none is a (3,0) Microsoft Symbol cmapWith multiple cmaps present, a (3,0) symbol cmap is required to disambiguate.
- 31-027 A font dictionary does not contain the ToUnicode entry and no exemption appliesA ToUnicode CMap is required unless the font uses MacRoman/MacExpert/WinAnsi encoding, or is a Type 1/Type 3 whose glyph names are all in the Adobe Glyph List or the Symbol set, or is a Type 0 whose descendant uses a standard Adobe character collection, or is a non-symbolic TrueType.
- 31-028 Unicode values in the ToUnicode CMap are zeroU+0000 is not a valid mapping target; it usually means the producer could not determine the character and wrote a placeholder.
- 31-029 Unicode values in the ToUnicode CMap are U+FEFF or U+FFFEByte-order marks are not characters and must not appear as mapping targets.
- 31-030 Characters used in text showing operators reference the .notdef glyphThe content stream paints glyph index 0, which is by definition "no glyph" — typically a hollow box or nothing at all.
Check your own file. Taggart does not check this condition yet, and lists it for you to confirm. Its validator is free and checks 75 of the 87 Matterhorn conditions software can decide — no watermark, no expiry, and no account needed up to 60 pages.
Taggart does not check this condition yet. A generated file that fails it is in the repository, with a test that fails the day Taggart starts catching it. Written on . The Acrobat steps follow Adobe’s documentation and were not walked through by hand. Last updated .