Check it first, read after. Two files, both produced by the production engine:
- **PDF/UA-2 reference document** — ISO 14289-2, PDF 2.0 container
- **PDF/UA-1 reference document** — ISO 14289-1, for comparison
Each contains every tagged construct exactly once: headings, paragraphs with language changes, lists, a definition list, a table with header cells, figures with alt text, a formula, links, footnotes, form fields with labels, and artifacts that are deliberately outside the logical tree. Run them through veraPDF:
$ verapdf -f ua2 --format text pdf-ua-2-reference.pdf
PASS pdf-ua-2-reference.pdf ua2
$ verapdf -f ua1 --format text pdf-ua-1-reference.pdf
PASS pdf-ua-1-reference.pdf ua1
All 51 templates in our gallery pass the same ua2 profile today. Here’s what the second edition actually demands, and why “it passed the validator” is only half of a verification.
UA-2 is not UA-1 with fixes
PDF/UA-1 (ISO 14289-1, 2014) is written on top of PDF 1.7. PDF/UA-2 (2024) is written on top of PDF 2.0 — and that is the whole story behind most of the differences. It isn’t a list of extra rules bolted onto the first edition; it is the same intent re-expressed in PDF 2.0’s tagging model.
The practical consequence surprises people: you cannot re-stamp a UA-1 file as UA-2. The two editions disagree about specific structures, so one output cannot satisfy both. The edition has to be chosen when the file is written. In our engine it is one option (pdfuaPart), and it changes the bytes in five distinct places.
The five changes that actually bite
1. The container version has to match the claim
ISO 14289-2 requires conformance to ISO 32000-2. A file whose header says %PDF-1.7 and whose catalogue carries no /Version is a 1.7 file, whatever its metadata claims. We shipped that bug: a UA-2 file with a 1.7 header, and veraPDF said PASS — because the profile checks prohibitions, not the container version. The validator’s silence was its boundary, not our proof.
Now the header follows the claim in both directions, and the check is eight bytes:
$ head -c 8 pdf-ua-2-reference.pdf
%PDF-2.0
$ head -c 8 pdf-ua-1-reference.pdf
%PDF-1.7Raising the version on a UA-1 file would be the same lie in reverse — ISO 14289-1 is written against ISO 32000-1.
2. Every element has a namespace, and not everything moved
In PDF 1.7 an element type is just a name: P means paragraph by convention. PDF 2.0 (§14.7.4.2) made membership explicit — an element carries /NS, and the same P in two namespaces is two types. UA-2 (§8.2.5.2) requires the standard types to live in the ISO 32000-2 namespace; without it a validator won’t even accept the root Document.
The trap is the second namespace. Several standard 1.7 types did not move to PDF 2.0 — TOC, TOCI, Code, Reference, BlockQuote, Index, BibEntry, Quote — and neither did anything non-standard mapped through /RoleMap, which is itself a 1.7 concept. Declaring those in the 2.0 namespace asserts something that namespace does not contain: in our case, eleven violations of §8.2.4, one per table-of-contents item plus the publishing types.
So a UA-2 file carries two namespace objects, and each element is routed to the one it actually belongs to.
3. Footnotes are FENote
Note is a standard PDF 1.7 type. In the ISO 32000-2 namespace it does not exist — the footnote type there is FENote (PDF 2.0 §14.8.4.7.2), and UA-2 §8.2.5.14 forbids Note without a role map. Under UA-1 the same footnote must stay Note, or the first-edition validator finds no standard type. Same document, same footnote, two different names depending on the edition claimed.
4. Destinations must be structural
UA-2 §8.8: an internal destination — a link, a bookmark, a table-of-contents entry — must point at a structure element, not at a page and a coordinate. It sounds bureaucratic and isn’t: a structural destination tells the assistive tool what opened, not merely where to look.
Putting a structure destination next to the page one doesn’t satisfy it (we measured: veraPDF judges /Dest itself and kept its six violations). And rewriting /Dest structurally is illegal under UA-1, where the first array element must be a page. Two branches, no middle.
5. A footnote and its citation must point at each other
UA-2 §8.2.5.14 wants the FENote to name every reference that cites it. Miss the reverse direction and veraPDF prints “Ref entry in the FENote does not reference structure elements … while these structure elements reference this FENote”. We shipped the one-directional version first and got exactly that.
Note what this rule is: in ISO 14289-1 there are exactly two machine rules about Note — that it has an /ID and that the /ID is unique. Nothing about being linked. Which brings us to the checkers.
Why one validator is not verification
veraPDF: what a PASS proves, and what it doesn’t
veraPDF is the reference implementation and it runs on every change we make to the engine: the ua1 and ua2 profiles over our reference documents and all 51 gallery templates, plus the 3b, 3u and 3a PDF/A profiles.
But a validator only checks what it can express as a rule, and “a rule with nothing to check also passes”. Two honest caveats we keep in front of ourselves:
- Coverage, not verdicts. The
ua1profile holds 106 rules. Our reference file passes all 106 and exercises 94 — the other twelve cover constructs the engine never produces (encryption, optional content, TrapNet, multimedia clips, embedded CMaps, a Type 1CharSet). A rule with nothing to check passes by default, so “106 of 106” would be true and worthless. - Coverage percentages are meaningless for
ua2. That profile carries well over a thousand rules, of which roughly 1,600 are the allowed-nesting table — which type may contain which. Activating them all needs a document containing every pair of types, which is a combinatorial exercise, not quality. (And the number is unreliable anyway: veraPDF truncates a success report at 10,000 checks, so a document and a strict superset of it report the same total.)
PAC: the second opinion that found real defects
PAC — the PDF Accessibility Checker, published free by the PDF/UA Foundation — implements the same standard independently and raises things the ISO machine rules leave as judgement. Every item below was a genuine defect in our output that veraPDF passed, found by PAC, and fixed in the engine:
- Untyped artifacts. A bare
/Artifact BMCis legal and tells a screen reader nothing — it cannot offer “skip repeating page elements” if it doesn’t know what repeats. Our sample had 28 artifact regions, 21 of them bare: table rules, a decorative band, field outlines. They now carry/Layout,/Paginationand the watermark subtype, per §14.8.2.2. - Figures without a bounding box. §14.8.5.4.3 wants
/BBoxon aFigureso the consumer knows where the picture sits. The raster path wrote it; the vector (SVG) path didn’t, and PAC flagged every SVG figure. - Footnotes nothing links to. “’Note’ element is not referenced by a ‘Link’ element.” Not an ISO rule — a PAC warning. We implemented it anyway (
/Refon both the link and the note), because a footnote you cannot reach is worse than one you can. That same work turned out to be required by UA-2, which asks for the reverse direction. - Figure/Form used where they don’t belong. “Possibly inappropriate use of a Figure/Form structure element” — code blocks and formulas wrapped in the wrong container.
Two independent implementations agreeing is evidence. One green screen is a screenshot.
The audits the standards don’t run
Two more gates, both ours, both hard-failing on the whole 51-template gallery:
- Content-stream state. Graphics-state operator pairing per ISO 32000-2, Figure 9 — an unbalanced
q/Qor aBDCthat never closes can leave a document that opens fine and tags wrong. Current state: zero violations across every template. - Structural audit. A ratchet, not a threshold: it counts structural oddities (a paragraph repeating on every page that may or may not be a running header) and fails if the count goes up. Judgement calls stay judgement calls instead of being patched to please a tool.
The half no machine can check
Tagging is mechanical. Correct tagging is not: whether that alt text describes the image, whether the reading order matches the argument, whether a heading is a heading or just big text. No validator will ever answer those, and PDF/UA says so.
That half lives in the editor, in the accessibility check, and it looks for the things a machine legitimately can flag:

- images with no alt text, alt text that is a filename, alt text that runs long enough to be a paragraph
- tables with no header cells
- heading levels that jump (H2 → H4)
- headings that look like body text, and body text that looks like a heading
- links whose text is “click here”, and links distinguished from body text by colour alone (WCAG 1.4.1)
- text below the contrast its size requires (WCAG 1.4.3), and table-cell, form-field or divider borders below 3:1 (WCAG 1.4.11) — the ones a low-vision reader loses first
- form fields with no label
- an empty document title, a missing document language
- empty text elements left behind while editing
A checklist you can apply to any PDF
| Question | How to check |
|---|---|
| Does the container match the claim? | head -c 8 file.pdf — UA-2 needs %PDF-2.0, UA-1 needs %PDF-1.7 |
| Is it tagged at all? | pdfinfo file.pdf → Tagged: yes |
| Does it satisfy the machine rules? | verapdf -f ua1 file.pdf or -f ua2 |
| Does the other implementation agree? | Open it in PAC and read the warnings, not just the errors |
| Is the reading order right? | Read the tag tree, or listen to it — no tool decides this |
| Do figures have meaningful alt text? | Read every one of them out loud |
| Are decorative elements artifacts? | They should be typed artifacts, not bare ones |
| Can you reach every footnote? | Follow the links; a note nothing references is a dead end |
Where we are, and what we’re not claiming
Done: the engine emits PDF/UA-2, the reference document and all 51 gallery templates pass veraPDF’s ua2 profile, headers match the claimed edition in both directions, and the contradictory PDF/UA-2 + PDF/A-3 combination is refused at the API rather than produced.
Not done: the editor doesn’t expose the switch yet. UA-2 also expects mathematical content to carry a MathML representation — we tag Formula, but we don’t attach MathML, so a maths-heavy document is tagged, not fully described.
And PDF/UA-1 stays the default, deliberately. Compliance language written to date names the first edition, it is the one that pairs with PDF/A-3a for dual archival + accessible files, and assistive software support for PDF 2.0 structures is still uneven. UA-2 becomes the better answer the moment those change — the engine will be waiting, and the same engine we just finished moving to Rust.
Meanwhile, everything on this page applies to the file you export today: tagged output is free on every plan, the accessibility check flags the human half before you send it, and both reference files above are re-checkable in about ten seconds.