DEV Community

An Empty VAST Wrapper Is Schema-Valid in 4.4. It Was Not in 2.0.

A VAST wrapper with no AdSystem, no VASTAdTagURI and no Impression validates against the VAST 4.4 draft schema. The same document has been invalid in every version from 2.0 through 4.2. It is one line of XSD, and it is almost certainly a side effect of the CTV Ad Portfolio restructure rather than a decision anyone made on purpose. I have filed it with IAB Tech Lab. This post is the working, because the reproduction is short enough that anyone can check it in about a minute. The change In vast_4.4.xsd on master, both vastInLine_type and vastWrapper_type wrap their children in a single compositor: an xs:choice with minOccurs zero and maxOccurs unbounded. That looks harmless. It is the idiom people reach for when they want to say "these children may appear in any order". What it actually says is stronger than that. In XSD, the cardinality on the compositor governs the content model, and the minOccurs on the individual child elements only describes a single selection from the choice. Set the choice itself to zero-or-more and every constraint underneath it stops binding. So the children still declare minOccurs="1". They are still, in effect, optional. The compositor in question Three consequences, not one The empty wrapper is the headline, but the compositor gives up three separate guarantees at once. Each is reproducible with xmllint against the published schema. What now validates in 4.4 - Everything is optional. An empty validates. So does an empty , with no AdSystem, no AdTitle, no Impression and no Creatives. - Everything repeats. maxOccurs="unbounded" on the choice means any branch can be selected repeatedly, so three elements in one InLine validate, even though AdSystem has always been exactly one. - Order stops mattering. 4.2 used xs:sequence, so the order was fixed. A choice imposes none, so before validates. Reproduction: all three validate against the published 4.4 schema A B C Check it yourself curl -sO https://raw.githubusercontent.com/InteractiveAdvertisingBureau/vast/master/vast_4.4.xsd xmllint --noout --schema vast_4.4.xsd empty-wrapper.xml # empty-wrapper.xml validates # the same shape against 4.2 xmllint --noout --schema vast_4.2.xsd empty-wrapper-42.xml # Element 'Wrapper': Missing child element(s). Expected is ( AdSystem ). What 4.2 actually required The contrast is worth being precise about, because the requirement did not live where you might expect. In 4.2, Wrapper_type extends AdDefinitionBase_type, and it is the base type that carries the required fields: AdSystem exactly once, Impression once or more. Wrapper_type then adds VASTAdTagURI as required and Creatives as optional. Both use xs:sequence. Impression in particular has been required on wrappers since 2.0. That is a twenty-year-old constraint, and the wrapper is exactly where it matters most, because a wrapper that fires no impression is a measurement hole in the middle of a chain. The schema went from expressing a content model to enumerating a vocabulary. Those are different jobs, and only one of them can gate anything. vastlint standards note Why this matters if you gate on the XSD Plenty of teams treat the published XSD as an acceptance gate: ad server ingest checks, partner certification, QA rigs that reject anything the schema will not accept. For those, 4.4 currently passes wrapper responses that cannot deliver an ad and cannot record an impression. It also sharpens a question the working group was already asking in a separate thread about whether the XSD is meant to be usable as a validator at all. My answer has not changed: it is not, and it never fully was. The prose has always carried requirements the schema does not express, which is the reason a rule-based validator exists in the first place. But there is a difference between a schema that is incomplete and a schema that is more permissive than the version it supersedes. The practical takeaway for anyone shipping 4.4 today: do not loosen your own checks to match the draft. Keep requiring AdSystem, Impression and VASTAdTagURI on wrappers, because the prose still does and every prior version did. The likely fix If the intent was order-independence, xs:all expresses that while keeping per-element cardinality intact. XSD 1.0 limits xs:all particles to maxOccurs one, so repeating elements like Impression need handling, but the required ones stay required. If the intent really was a fully open content model, then the schema and the prose have diverged and the annotation should say so out loud, so that nobody builds a gate on top of it expecting otherwise. Either way it is a small patch. I have offered to write it. Validate a 4.4 tag against the prose, not just the schema vastlint checks VAST 2.0 through the 4.4 draft against rules derived from the specification text, not only the XSD, so a wrapper missing AdSystem or Impression still fails. Paste a tag and see. Nothing is stored. Sources and further reading - IAB Tech Lab VAST issue #58 (GitHub) The filed report, with the full reproduction and the 4.2 comparison table. - vast_4.4.xsd on master (IAB Tech Lab) The published draft schema. See vastInLine_type and vastWrapper_type. - VAST 4.4: what actually shipped (vastlint) The full technical breakdown of the 4.4 draft, content model by content model. - VAST 4.3 to 4.4 migration guide (vastlint) Element-by-element changes with a migration checklist. - Wrapper chains and where they break (vastlint) What a wrapper has to carry for a chain to resolve and measure correctly. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.