Common VAST tag 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.
Use the right tool for these VAST errors
If you already have the XML, validate it. If you only have a live VAST URL, use the tester first. If the failure involves wrappers, redirects, or missing VASTAdTagURI, inspect the chain hop by hop.
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>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
→ 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>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
→ 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>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
→ 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%">VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
→ 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 id="example-1">
<InLine>
<AdSystem>Example Ad Server</AdSystem>
<AdServingId>serving-123</AdServingId>
<AdTitle>Example Ad</AdTitle>
<Impression><![CDATA[https://track.example.com/impression]]></Impression>
<Creatives>
<Creative>
<UniversalAdId idRegistry="ad-id.org">8465903</UniversalAdId>
<Linear>
<Duration>00:00:30</Duration>
<TrackingEvents>
<Tracking event="start"><![CDATA[https://track.example.com/start]]></Tracking>
<Tracking event="firstQuartile"><![CDATA[https://track.example.com/firstQuartile]]></Tracking>
<Tracking event="midpoint"><![CDATA[https://track.example.com/midpoint]]></Tracking>
<Tracking event="thirdQuartile"><![CDATA[https://track.example.com/thirdQuartile]]></Tracking>
<Tracking event="complete"><![CDATA[https://track.example.com/complete]]></Tracking>
</TrackingEvents>
<MediaFiles>
<MediaFile type="video/mp4" width="1280" height="720" delivery="progressive">
<![CDATA[https://cdn.example.com/ad.mp4]]>
</MediaFile>
</MediaFiles>
</Linear>
</Creative>
</Creatives>
</InLine>
</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>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
→ Rule reference: VAST-2.0-nonlinear-dimensions
Catch all of these automatically
Every error on this page maps to a documented vastlint rule. Paste a tag into the web validator or run vastlint validate tag.xml in your terminal to check all of them instantly.