google/ExoPlayer · error · IllegalArgumentException
The item must specify its mimeType
Error message
The item must specify its mimeType
What it means
IllegalArgumentException thrown by DefaultMediaItemConverter.toMediaQueueItem when mediaItem.localConfiguration.mimeType is null. The Cast SDK requires a content type for MediaInfo, and unlike a player pipeline the Cast route has no sniffing step, so the item must carry an explicit MIME type. The converter also requires localConfiguration itself (non-null check above), i.e. a concrete URI.
Source
Thrown at extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.java:101
metadataBuilder.setComposer(metadata.getString(MediaMetadata.KEY_COMPOSER));
}
if (metadata.containsKey(MediaMetadata.KEY_DISC_NUMBER)) {
metadataBuilder.setDiscNumber(metadata.getInt(MediaMetadata.KEY_DISC_NUMBER));
}
if (metadata.containsKey(MediaMetadata.KEY_TRACK_NUMBER)) {
metadataBuilder.setTrackNumber(metadata.getInt(MediaMetadata.KEY_TRACK_NUMBER));
}
}
// `mediaQueueItem` came from `toMediaQueueItem()` so the custom JSON data must be set.
return getMediaItem(
Assertions.checkNotNull(mediaInfo.getCustomData()), metadataBuilder.build());
}
@Override
public MediaQueueItem toMediaQueueItem(MediaItem mediaItem) {
Assertions.checkNotNull(mediaItem.localConfiguration);
if (mediaItem.localConfiguration.mimeType == null) {
throw new IllegalArgumentException("The item must specify its mimeType");
}
MediaMetadata metadata =
new MediaMetadata(
MimeTypes.isAudio(mediaItem.localConfiguration.mimeType)
? MediaMetadata.MEDIA_TYPE_MUSIC_TRACK
: MediaMetadata.MEDIA_TYPE_MOVIE);
if (mediaItem.mediaMetadata.title != null) {
metadata.putString(MediaMetadata.KEY_TITLE, mediaItem.mediaMetadata.title.toString());
}
if (mediaItem.mediaMetadata.subtitle != null) {
metadata.putString(MediaMetadata.KEY_SUBTITLE, mediaItem.mediaMetadata.subtitle.toString());
}
if (mediaItem.mediaMetadata.artist != null) {
metadata.putString(MediaMetadata.KEY_ARTIST, mediaItem.mediaMetadata.artist.toString());
}
if (mediaItem.mediaMetadata.albumArtist != null) {
metadata.putString(
MediaMetadata.KEY_ALBUM_ARTIST, mediaItem.mediaMetadata.albumArtist.toString());View on GitHub (pinned to dd430f7053)
Solutions
- Set an explicit MIME type when building every castable item: MediaItem.Builder().setUri(...).setMimeType(MimeTypes.VIDEO_MP4)
- Derive the type from the URI extension or your own manifest metadata when the source data lacks it
- Use a custom MediaItemConverter if you must supply the type at conversion time rather than on every item
- Guard before conversion: reject or enrich items whose localConfiguration.mimeType is null instead of crashing
Example fix
// before
MediaItem item = new MediaItem.Builder().setUri(videoUrl).build();
MediaQueueItem queueItem = converter.toMediaQueueItem(item); // throws
// after
MediaItem item = new MediaItem.Builder()
.setUri(videoUrl)
.setMimeType(videoUrl.endsWith(".m3u8") ? MimeTypes.APPLICATION_M3U8 : MimeTypes.VIDEO_MP4)
.build();
MediaQueueItem queueItem = converter.toMediaQueueItem(item); Defensive patterns
Strategy: validation
Validate before calling
MediaItem safeForCast(MediaItem item, String uri) {
MediaItem.Builder b = item.buildUpon();
if (item.localConfiguration == null
|| item.localConfiguration.mimeType == null) {
b.setMimeType(guessMimeType(uri)); // e.g. from extension: .mpd/.m3u8/.mp4/.mp3
}
return b.build();
}
static String guessMimeType(String uri) {
if (uri.endsWith(".m3u8")) return MimeTypes.APPLICATION_M3U8;
if (uri.endsWith(".mpd")) return MimeTypes.APPLICATION_MPD;
if (uri.endsWith(".mp4")) return MimeTypes.VIDEO_MP4;
return MimeTypes.VIDEO_MP4; // sensible default; adjust to your catalog
} Try / catch
try {
MediaQueueItem queueItem = converter.toMediaQueueItem(item);
} catch (IllegalArgumentException e) {
// item missing mimeType or localConfiguration: enrich and retry once
item = item.buildUpon().setMimeType(MimeTypes.VIDEO_MP4).build();
queueItem = converter.toMediaQueueItem(item);
} Prevention
- Set setMimeType on every MediaItem at creation time — casting needs it even when local playback does not
- Centralize MediaItem construction in a factory that always sets uri + mimeType
- Prefer constant MimeTypes.* values over hand-written strings
When it happens
Trigger: Building a MediaItem with only setUri() and passing it to a MediaItemConverter for cast queuing; MediaItem built from a MediaMetadata-only source; URI schemes where ExoPlayer would infer the type locally (progressive/adaptive) so the developer never set a MIME type until casting.
Common situations: App plays fine locally but crashes when the cast button routes the same MediaItem; items created from database rows with uri only; migrating to Media3 where setMimeType moved under RequestMetadata/LocalConfiguration.
Related errors
- Unexpected color filter ${colorFilterSelection}
- ERROR_CODE_FAILED_RUNTIME_CHECK
- Could not delete the previous export output file
- Could not create the export output file
- Failed to load MediaPipeShaderProgram
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/d8cfc66860aa5ebb.
Report an issue: GitHub.