google/ExoPlayer · error · IOException
${errorMessage} [errorCode: ${errorCode}]
Error message
${errorMessage} [errorCode: ${errorCode}] What it means
Thrown by the stream-resolution loader in ImaServerSideAdInsertionMediaSource when the IMA SDK reported a stream request error and no content URI was obtained before the load was cancelled. The message concatenates the IMA error message and IMA error code, so the underlying cause comes straight from the IMA stream request API.
Source
Thrown at extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaServerSideAdInsertionMediaSource.java:1065
(streamUri, subtitles) -> {
contentUri = Uri.parse(streamUri);
conditionVariable.open();
});
if (adErrorListener != null) {
adsLoader.addAdErrorListener(adErrorListener);
}
adsLoader.addAdsLoadedListener(this);
adsLoader.addAdErrorListener(this);
adsLoader.requestStream(request);
while (contentUri == null && !cancelled && !error) {
try {
conditionVariable.block();
} catch (InterruptedException e) {
/* Do nothing. */
}
}
if (error && contentUri == null) {
throw new IOException(errorMessage + " [errorCode: " + errorCode + "]");
}
} finally {
adsLoader.removeAdsLoadedListener(this);
adsLoader.removeAdErrorListener(this);
if (adErrorListener != null) {
adsLoader.removeAdErrorListener(adErrorListener);
}
}
}
@Override
public void cancelLoad() {
cancelled = true;
}
// AdsLoader.AdsLoadedListener implementation.
@MainThreadView on GitHub (pinned to dd430f7053)
Solutions
- Inspect the errorMessage/errorCode in the thrown IOException — they are IMA's own diagnostics (e.g. stream download failure vs invalid asset key) and identify the exact problem.
- Validate the SSAI URI parameters: correct assetKey (live) or contentSourceId+videoId (VOD), and a supported FORMAT (dash/hls); build it with ImaServerSideAdInsertionUriBuilder to avoid mistakes.
- Check network reachability of the IMA/DAI endpoints from the device and retry with a known-good public DAI test stream (Google provides reference asset keys).
- Update the IMA extension and IMA SDK to the latest matching versions, then re-test — older combinations have known stream-request failures.
Example fix
// before
String uri = "imasky://example.com?asset_key=WRONG&format=0"; // errorCode surfaced in IOException
// after
String uri = new ImaServerSideAdInsertionUriBuilder()
.setAssetKey("your-asset-key")
.setFormat(C.CONTENT_TYPE_DASH)
.build()
.toString(); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate SSAI URI params before playback:
@Nullable String assetKey = uri.getQueryParameter("asset_key");
@Nullable String vid = uri.getQueryParameter("v");
if ((assetKey == null) && (uri.getQueryParameter("cmsid") == null || vid == null)) {
Log.e(TAG, "SSAI URI missing required params");
} Try / catch
// in Loadable catch / Player.Listener:
catch (IOException e) { // message contains IMA errorMessage + errorCode
if (e.getMessage() != null && e.getMessage().contains("errorCode")) showAdStreamError(e.getMessage());
} Prevention
- Build SSAI URIs only with ImaServerSideAdInsertionUriBuilder.
- Keep one validated DAI test stream in your test suite to distinguish config vs network failures.
- Surface the embedded IMA errorCode to your telemetry.
When it happens
Trigger: ImaServerSideAdInsertionMediaSource requests a DAI stream (adsLoader.requestStream(request)); onAdsLoadError sets error=true with errorMessage/errorCode from IMA's AdError; the blocking wait loop exits and, because contentUri is still null, this IOException propagates out of the Loader. Typical triggers: invalid asset key / content source ID, DRM or network failures reaching the DAI backend, malformed stream request parameters built by ImaServerSideAdInsertionUriBuilder.
Common situations: Typo'd or expired asset_key/cmsId+videoId in the SSAI URI; a device without network access or behind a firewall blocking DAI endpoints; an IMA SDK/DAI backend version mismatch; test streams that have been deprovisioned by Google.
Related errors
- 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
- ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/add8d5d8c07dce0a.
Report an issue: GitHub.