google/ExoPlayer · error · IllegalStateException
Failed to find cue point
Error message
Failed to find cue point
What it means
Thrown by AdTagLoader when an IMA SDK cue point (an ad break time reported by the ads SDK) cannot be matched to any ad group in the current AdPlaybackState. The code converts the cue point to microseconds and searches for an ad group within THRESHOLD_AD_MATCH_US; if none matches, the mapping between what IMA reports and what ExoPlayer scheduled is broken, so it fails fast rather than misattributing ads.
Source
Thrown at extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/AdTagLoader.java:1281
playerPositionUs, msToUs(contentDurationMs));
}
return adGroupIndex;
}
private int getAdGroupIndexForCuePointTimeSeconds(double cuePointTimeSeconds) {
// We receive initial cue points from IMA SDK as floats. This code replicates the same
// calculation used to populate adGroupTimesUs (having truncated input back to float, to avoid
// failures if the behavior of the IMA SDK changes to provide greater precision).
float cuePointTimeSecondsFloat = (float) cuePointTimeSeconds;
long adPodTimeUs = Math.round((double) cuePointTimeSecondsFloat * C.MICROS_PER_SECOND);
for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) {
long adGroupTimeUs = adPlaybackState.getAdGroup(adGroupIndex).timeUs;
if (adGroupTimeUs != C.TIME_END_OF_SOURCE
&& Math.abs(adGroupTimeUs - adPodTimeUs) < THRESHOLD_AD_MATCH_US) {
return adGroupIndex;
}
}
throw new IllegalStateException("Failed to find cue point");
}
private String getAdMediaInfoString(@Nullable AdMediaInfo adMediaInfo) {
@Nullable AdInfo adInfo = adInfoByAdMediaInfo.get(adMediaInfo);
return "AdMediaInfo["
+ (adMediaInfo == null ? "null" : adMediaInfo.getUrl())
+ ", "
+ adInfo
+ "]";
}
private static long getContentPeriodPositionMs(
Player player, Timeline timeline, Timeline.Period period) {
long contentWindowPositionMs = player.getContentPosition();
if (timeline.isEmpty()) {
return contentWindowPositionMs;
} else {
return contentWindowPositionMsView on GitHub (pinned to dd430f7053)
Solutions
- Verify the ad tag (VMAP break times) is self-consistent and does not declare near-duplicate breaks closer together than THRESHOLD_AD_MATCH_US.
- Update the IMA SDK and ExoPlayer IMA extension to matching, current versions — precision and rounding behavior of cue points has changed across IMA releases.
- Do not share one AdTagLoader/AdsLoader instance across media items with different ad configurations; release and recreate per stream.
- If you construct AdPlaybackState yourself, ensure adGroupTimesUs are derived with the same float-truncation + Math.round(µs) math shown in the source, so IMA-reported cue points land within the threshold.
Defensive patterns
Strategy: validation
Validate before calling
// Before resolving cue points, confirm a matching ad group exists:
float cueFloat = (float) cuePointTimeSeconds;
long podUs = Math.round((double) cueFloat * C.MICROS_PER_SECOND);
boolean matches = false;
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
long t = adPlaybackState.getAdGroup(i).timeUs;
if (t != C.TIME_END_OF_SOURCE && Math.abs(t - podUs) < 10_000L) matches = true;
}
if (!matches) Log.w(TAG, "Cue point " + podUs + "us has no ad group; check ad tag"); Try / catch
try { int idx = resolveAdGroupIndexForCuePoint(cuePointTimeSeconds); } catch (IllegalStateException e) { Log.w(TAG, "Cue point mismatch — verify ad tag consistency", e); skipCuePoint(); } Prevention
- Derive adGroupTimesUs and IMA cue points from the same source math (float truncate + µs round).
- Keep IMA SDK and ExoPlayer IMA extension versions in lockstep.
- Never share one AdsLoader across items with different ad configurations.
When it happens
Trigger: Calling the cue-point resolution path after IMA fires ADS_LOADER / content resume with cue points whose times differ from the adGroupTimesUs ExoPlayer derived at preparation time — e.g. the ad tag declares breaks at 15s but the IMA SDK later reports 15.05s beyond the match threshold, or ad groups were removed/modified concurrently.
Common situations: A mis-authored VAST/VMAP ad tag whose cue points drift from the declared break times; an IMA SDK version change that alters cue-point precision or timing; concurrent modification of AdPlaybackState (e.g. server-side ad insertion data merged while client-side cue points arrive); playlists where the same AdsLoader is reused across items with different ad break layouts.
Related errors
- ${errorMessage} [errorCode: ${errorCode}]
- Multiple IMA server side ad insertion sources not supported.
- Invalid URI scheme or authority.
- Unsupported stream format:${format}
- No unplayed ad group found before or at the start time us %d
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/1269df980b8c9791.
Report an issue: GitHub.