Matterhorn 31-004 · PDF/UA-1 UA1:7.21.3.2-1
CIDToGIDMap must be /Identity or a stream, nothing else
CIDToGIDMap must be either the name /Identity or a stream mapping CIDs to glyph indices.
The condition, as the protocol states it. “A Type 2 CID font contains neither a stream nor the name Identity as the value of the CIDToGIDMap entry.”
Matterhorn Protocol 1.1, checkpoint 31, index 31-004, section UA1:7.21.3.2-1. Software can decide this one on its own.
What a screen reader actually does
Glyph lookup is undefined, so text extraction is unreliable.
What the entry is for
A composite font whose descendant is /CIDFontType2 is a TrueType font addressed by CID. TrueType programs do not know about CIDs: they draw glyphs by glyph index, a position in the program’s own glyf table. Something has to turn the CID the CMap produced into the glyph index the program understands, and that is /CIDToGIDMap:
13 0 obj
<< /Type /Font /Subtype /CIDFontType2
/BaseFont /ABCDEF+Calibri
/CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >>
/FontDescriptor 16 0 R
/W [ ... ]
/CIDToGIDMap /Identity % CID n is glyph n
>>
ISO 32000-1 allows it two forms. The name /Identity says the CID is the glyph index — the normal arrangement for an embedded subset written with an Identity-H encoding. A stream is a lookup table: two bytes per CID, big-endian, so the glyph for CID c sits at bytes 2c and 2c+1. That is what a producer writes when its CIDs come from a collection such as Adobe-Japan1 and the TrueType font numbers its glyphs differently.
This is not an East Asian corner of the format. A Latin document exported to PDF often sets its text in TrueType-based CID fonts — pdffonts lists them as CID TrueType — and every one of them has, or should have, this entry.
What counts as a failure
Condition 31-004 is a /CIDToGIDMap that is present but is neither of those: a different name, an array, a number, a dictionary. In practice the names are the interesting ones, because they come from small mistakes:
/Identity-H— the CMap’s name, written into the font’s slot./identity— PDF names are case-sensitive, so this is a different name from/Identity.
An entry that is missing altogether is the separate condition 31-005.
What breaks
The value controls glyph selection, and an invalid value leaves it undefined. A viewer has to do something, and what it does is its own choice: it might assume /Identity, which is right if that is what the producer meant, or treat the font as unusable and substitute or draw nothing. Two viewers can render the same page differently, and neither is wrong, because the file did not say.
The text a screen reader gets usually survives, because it comes from the ToUnicode CMap, which maps codes to Unicode without passing through /CIDToGIDMap at all. On the test file used for this page — a CIDFontType2 with /CIDToGIDMap /Identity-H and a correct ToUnicode — Poppler’s pdftotext complained and still extracted the text correctly. What can be lost is the page as drawn. Where a viewer guesses wrong, correct words are announced over wrong glyphs — the mismatch that a sighted reviewer, a low-vision user and a screen-reader user will each report differently.
How to check it free
Poppler reports it directly. Running pdffonts or pdftotext over the file prints:
Syntax Error: Invalid CIDToGIDMap entry in CID font
when it loads such a font. It does not say which font, so follow up with qpdf.
qpdf. pdffonts prints each font’s object number; qpdf file.pdf --show-object=12 shows the Type 0 font, and the object in its /DescendantFonts array is the one to read for /CIDToGIDMap.
veraPDF with its PDF/UA-1 profile tests the entry under clause 7.21.3.2.
Acrobat Pro shows it, read-only, in Preflight: All tools → Use print production → Preflight, then Options → Browse Internal PDF Structure, and open the font from the page’s Resources down to its DescendantFonts. Adobe’s documentation describes the window as a viewer: you can navigate the structure and fonts but not edit them.
How to fix it
Acrobat has no command for this. Adobe’s advice for character-encoding problems is to re-create the PDF, and re-exporting from the source is the dependable fix.
If you can establish what the producer meant, it is also a one-value edit. For a subset embedded with an Identity-H encoding, /Identity is the likely intent, and it can be tested: qpdf --json-output with --json-object writes the CIDFont out as JSON, you change the value to "/Identity", apply it with --update-from-json, and render the result against the source document. If the glyphs match, that was the mapping. If they do not, the producer meant a lookup table, the table is not in the file, and the source is the only way back.
What Taggart does
Taggart reports a Type 2 CID font whose /CIDToGIDMap is a name other than /Identity — /Identity-H, /identity — as 31-004. Names are case-sensitive, so /identity is reported too. A stream is accepted. A missing /CIDToGIDMap is a different condition, 31-005.
Until October 2026 the check took every value for a stream, because it looked for the method that reads stream data and, in the PDF library Taggart uses, every object has one. It reported nothing. A test in the repository now builds a file with exactly that value and expects the finding.
There is no fix for either in Taggart.
How Taggart handles it
Taggart checks for this condition automatically and reports it as a blocker, with where in the file it found it.
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
What are the two allowed values?
The name /Identity, meaning CID n is glyph n in the embedded TrueType program, or a stream of two-byte big-endian glyph indices, one per CID, so that the glyph for CID c is at bytes 2c and 2c+1. Nothing else is defined.
Is /Identity-H close enough?
No. Identity-H is a CMap — it belongs in the Type 0 font's /Encoding, not in the CIDFont's /CIDToGIDMap. PDF names are exact, so /Identity-H, /identity and /IDENTITY are all simply not /Identity.
Does this affect what a screen reader says?
Usually not directly. Glyph lookup is what this entry controls; text extraction normally comes from the ToUnicode CMap, which does not pass through it. What it affects is what is drawn — and a page whose glyphs are wrong is wrong for everyone reading it by eye, including people using magnification.
Does Taggart report it?
Not today. The check exists, but it decides whether the value is a stream in a way every value passes, so an invalid name is taken for a stream. Use Poppler or veraPDF for this one until that is fixed.
Where this sits in the standards
| Standard | Reference |
|---|---|
| Matterhorn Protocol 1.1 | Checkpoint 31 (Fonts), index 31-004 |
| PDF/UA-1 (ISO 14289-1) | Clause 7.21.3.2-1 |
| 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-005 A Type 2 CID font does not contain a CIDToGIDMap entryThe entry is absent entirely.
- 31-011 The embedded font program does not contain glyphs for all referenced glyphsThe subset embedded in the file is missing glyphs the content stream asks for — very common when a document is edited after subsetting.
- 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.
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-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-011 The embedded font program does not contain glyphs for all referenced glyphsThe subset embedded in the file is missing glyphs the content stream asks for — very common when a document is edited after subsetting.
- 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’s validator is free and unlimited — 75 of the 87 Matterhorn conditions software can decide, with the other 12 listed for you to confirm; no watermark, no expiry, and no account needed up to 60 pages.
Checked with Taggart on a generated file that fails this condition on . The Acrobat steps follow Adobe’s documentation and were not walked through by hand. Last updated .