Skip to main content

Command Palette

Search for a command to run...

The VAST Errors That Quietly Kill Video Ad Fill (and How to Catch Them)

Most VAST tags do not fail loudly. They under-deliver. Here are the errors that drain fill and revenue, and how to catch them before they ship.

Updated
5 min read

If you serve video or CTV ads, you have shipped a broken VAST tag. Everyone has. The problem is that VAST rarely fails in a way you notice. The player does not throw a red banner. It just drops the impression, falls back to the next bid, and moves on. Your fill rate slips two points, nobody can say why, and the tag still "works" when you paste it into a test player.

VAST is the IAB XML template that tells a video player what ad to load and which tracking URLs to fire. It has been around since 2008 and spans versions 2.0 through 4.3, which is part of the problem: a tag that is valid for one player and version can be quietly wrong for another. Below are the errors that cost the most fill in practice, why they hurt, and how to catch them before a tag reaches production.


1. Wrapper chains that never resolve

A VAST <Wrapper> points at another VAST document via <VASTAdTagURI>. That target can point at another wrapper, and so on. Every hop adds latency and a new chance to fail. Players cap the chain (the spec suggests a limit, many SSPs enforce five), and once you blow the cap the player abandons the impression.

<Wrapper>
  <VASTAdTagURI><![CDATA[https://adserver.example/vast?p=2]]></VASTAdTagURI>
</Wrapper>

The failure mode is invisible: each hop is individually valid, but the chain as a whole times out. You only see it as lost fill. When you debug a live tag, follow every redirect and count the hops. A VAST inspector that unrolls the wrapper chain for you saves a lot of manual curl-and-paste.

2. Missing or malformed tracking URLs

Impression and quartile tracking is where money is counted. A <Impression> node with a non-CDATA URL, an unescaped ampersand, or an http:// URL on an https:// page will silently fail to fire. The ad still plays. You just do not get paid for it, or your measurement partner under-counts and your campaign looks like it underdelivered.

<Impression><![CDATA[https://track.example/imp?cb=123&pid=9]]></Impression>

The ampersand has to be inside CDATA or XML-escaped. The scheme has to match the page. These are trivial to miss by eye and trivial to catch with a VAST validator that flags mixed content and malformed tracking nodes.

3. MediaFile sets that exclude half your inventory

<MediaFile> declares the actual video: its type, width, height, bitrate, and delivery. A common revenue leak is shipping a single MP4 at one bitrate. CTV devices, low-bandwidth mobile, and HLS-only players all need options. If none of your media files match the player's constraints, the player rejects the ad even though the XML is perfectly valid.

This is the most expensive "valid but wrong" error in VAST. Validate the structure, then sanity-check that your media file set actually spans the codecs, bitrates, and aspect ratios your inventory demands.

4. Version drift between 2.0 and 4.3

Elements move between versions. <Category> and the <UniversalAdId> requirement arrive in later specs. VPAID is deprecated in 4.x in favor of SIMID. An attribute that is optional in 3.0 can be required in 4.2. A tag authored against one version and served to a player expecting another produces validation warnings that some players treat as fatal.

If you support multiple buyers, you cannot assume one version. The VAST versions guide lays out what changed where, and validating against the specific target version is the only way to be sure a tag is correct for the player that will actually render it.

5. Companion and SIMID misconfiguration

Companion banners and SIMID interactive components have their own required attributes and tracking. They fail independently of the main creative, so a tag can render the video fine and silently drop the companion or the interactive layer. Because the primary creative looks healthy, these are the errors that survive a casual eyeball test the longest.


How to catch these before they ship

The pattern across all five is the same: the tag is syntactically valid XML, so a browser or a quick paste-into-a-player test says "fine," while a specific rule violation quietly costs you the impression. Eyeballing XML does not scale, and neither does discovering the problem from a fill-rate dip a week later.

What works is validating every tag against an explicit rule set tied to the target VAST version, in CI or before you hand a tag to a buyer. vastlint is an open-source, Rust-based linter that does exactly this: it checks a tag against 180+ rules covering VAST 2.0–4.3 (plus VMAP, DAAST, VPAID, and SIMID), each rule carrying a stable ID, a severity, and a spec reference so you know why it fired. You can run it from the CLI, as a library, or through an MCP server, and the full rule reference and common VAST errors catalog are public.

Paste a tag into the online validator, or wire the CLI into the step where tags get generated, and the five failure modes above stop being mysteries you diagnose after the revenue is already gone.


vastlint is open source. If you debug VAST for a living and have a failure mode that is not in the rule set, the repo takes issues and PRs.