Common VAST XML errors and how to fix them
Most VAST ad delivery failures come from the same handful of mistakes. This guide covers the errors that vastlint catches most frequently, with examples and fixes for each.
1. Missing <Impression> element
Every inline VAST ad must contain at least one <Impression> element with a valid URL. Without it, the impression cannot be tracked and most players will discard the tag entirely.
<!-- ❌ Missing Impression -->
<InLine>
<AdTitle>My Ad</AdTitle>
<Creatives>...</Creatives>
</InLine>
<!-- ✅ Fixed -->
<InLine>
<AdTitle>My Ad</AdTitle>
<Impression><![CDATA[https://track.example.com/impression]]></Impression>
<Creatives>...</Creatives>
</InLine>→ Rule reference: VAST-2.0-inline-impression
2. Invalid <Duration> format
Duration must follow the HH:MM:SS or HH:MM:SS.mmm format. A bare number like 30 or an ISO 8601 duration like PT30S will fail.
<!-- ❌ Wrong format -->
<Duration>30</Duration>
<Duration>PT30S</Duration>
<!-- ✅ Correct -->
<Duration>00:00:30</Duration>
<Duration>00:00:30.000</Duration>→ Rule reference: VAST-2.0-duration-format
3. Empty or missing <MediaFile>
Inline ads require at least one <MediaFile> element. The URL inside must point to a valid video asset. An empty <MediaFile/> tag or a missing URL causes the ad to fail silently.
→ Rule reference: VAST-2.0-mediafiles-empty
4. Malformed tracking URLs
All URIs in <Impression>, <Tracking>, <ClickThrough>, and <MediaFile> must be valid URLs. Common mistakes include missing the protocol (http:// or https://), using spaces, or leaving macros unescaped.
<!-- ❌ Missing protocol -->
<Impression><![CDATA[track.example.com/imp]]></Impression>
<!-- ❌ Unescaped ampersands -->
<Impression><![CDATA[https://track.example.com/imp?a=1&b=2]]></Impression>
<!-- ✅ Correct -->
<Impression><![CDATA[https://track.example.com/imp?a=1&b=2]]></Impression>→ Rule reference: VAST-2.0-impression-url
5. VPAID creatives on CTV / VPAID-blocked environments
VPAID (apiFramework="VPAID") is blocked on most CTV platforms and increasingly on mobile. Serving a VPAID tag where it's unsupported produces no error from the player. The slot just goes dark.
vastlint flags all VPAID tags with an advisory so you can catch them before delivery. The fix is to serve a VAST-native creative (MP4/WebM) and use OMID for measurement instead.
→ Rule reference: VAST-4.1-vpaid-in-interactive-context
6. Version mismatch
A VAST document declares its version in the root <VAST version="X.X"> attribute. Using elements introduced in VAST 4.x (like <UniversalAdId>) in a tag declared as 3.0, or omitting required 4.x fields, produces version mismatch warnings.
→ Rule reference: VAST-2.0-root-version-value
7. Missing <VASTAdTagURI> in wrapper ads
Wrapper ads (type <Wrapper>) must contain a <VASTAdTagURI> pointing to the next tag in the chain. Without it, the player has no way to resolve the wrapper.
→ Rule reference: VAST-2.0-wrapper-vastadtaguri
8. Duplicate <Impression> URIs
Multiple <Impression> elements are allowed, but they should have different URIs. Identical URIs fire the same pixel twice, inflating impression counts and creating discrepancy alerts.
→ Rule reference: VAST-2.0-duplicate-impression
9. Invalid skipoffset attribute
The skipoffset on <Linear> must be a time offset (HH:MM:SS) or a percentage (50%). Values like 5 (bare number) or skip (string) are invalid.
<!-- ❌ Invalid skipoffset -->
<Linear skipoffset="5">
<!-- ✅ Correct -->
<Linear skipoffset="00:00:05">
<Linear skipoffset="25%">→ Rule reference: VAST-3.0-skipoffset-format
10. No <Ad> element at all
A VAST document with zero <Ad> elements is technically a “no-ad response.” While valid per spec (it signals no fill), an unexpected no-ad response from a tag that should be returning an ad usually indicates a server-side issue.
→ Rule reference: VAST-2.0-ad-no-inline-or-wrapper
11. Using HTTP instead of HTTPS
Most players and browsers block mixed content. All media URLs, tracking pixels, and companion assets should use https://. vastlint flags HTTP URLs as advisories.
→ Rule reference: VAST-2.0-mediafile-url
12. Missing version attribute on <VAST>
The root <VAST> element must have a version attribute. Without it, vastlint cannot determine which spec version to validate against, and most players may treat the tag as invalid or default to inconsistent behavior.
<!-- ❌ Missing version -->
<VAST>
<Ad>...</Ad>
</VAST>
<!-- ✅ Correct -->
<VAST version="4.2">
<Ad>...</Ad>
</VAST>→ Rule reference: VAST-2.0-root-version
<NonLinear> missing width or height (VAST 4.2)
Inside <NonLinearAds>, every <NonLinear> element requires both a width and a height attribute. This requirement has been part of the IAB VAST spec since version 2.0 and remains in VAST 4.2 and 4.3. Players use these attributes to reserve layout space and match the right creative rendition. A <NonLinear> element without both attributes will typically be skipped or misrendered.
<!-- ❌ Missing width and height on NonLinear -->
<NonLinearAds>
<NonLinear>
<StaticResource creativeType="image/gif">
<![CDATA[https://example.com/overlay.gif]]>
</StaticResource>
</NonLinear>
</NonLinearAds>
<!-- ✅ Fixed: add width and height attributes -->
<NonLinearAds>
<NonLinear width="480" height="70">
<StaticResource creativeType="image/gif">
<![CDATA[https://example.com/overlay.gif]]>
</StaticResource>
</NonLinear>
</NonLinearAds>→ Rule reference: VAST-2.0-nonlinear-dimensions
Catch all of these automatically
Every error on this page is one of the 118 rules in vastlint. Paste a tag into the web validator or run vastlint validate tag.xml in your terminal to check all of them instantly.