google/ExoPlayer · error · IllegalStateException
Missing implementation to handle COMMAND_SET_MEDIA_ITEM(S)
Error message
Missing implementation to handle COMMAND_SET_MEDIA_ITEM(S)
What it means
Player.setMediaItem/setMediaItems are dispatched by SimpleBasePlayer to handleSetMediaItems(List, int startIndex, long startPositionMs). The default throws IllegalStateException (note the '(S)' in the message covering both single and plural APIs) when COMMAND_SET_MEDIA_ITEM or COMMAND_CHANGE_MEDIA_ITEMS is advertised without the override. If only COMMAND_SET_MEDIA_ITEM is available, the list will contain exactly one item.
Source
Thrown at library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java:3182
/**
* Handles calls to {@link Player#setMediaItem} and {@link Player#setMediaItems}.
*
* <p>Will only be called if {@link Player#COMMAND_SET_MEDIA_ITEM} or {@link
* Player#COMMAND_CHANGE_MEDIA_ITEMS} is available. If only {@link Player#COMMAND_SET_MEDIA_ITEM}
* is available, the list of media items will always contain exactly one item.
*
* @param mediaItems The media items to add.
* @param startIndex The index at which to start playback from, or {@link C#INDEX_UNSET} to start
* at the default item.
* @param startPositionMs The position in milliseconds to start playback from, or {@link
* C#TIME_UNSET} to start at the default position in the media item.
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleSetMediaItems(
List<MediaItem> mediaItems, int startIndex, long startPositionMs) {
throw new IllegalStateException("Missing implementation to handle COMMAND_SET_MEDIA_ITEM(S)");
}
/**
* Handles calls to {@link Player#addMediaItem} and {@link Player#addMediaItems}.
*
* <p>Will only be called if {@link Player#COMMAND_CHANGE_MEDIA_ITEMS} is available.
*
* @param index The index at which to add the items. The index is in the range 0 <= {@code
* index} <= {@link #getMediaItemCount()}.
* @param mediaItems The media items to add.
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleAddMediaItems(int index, List<MediaItem> mediaItems) {
throw new IllegalStateException("Missing implementation to handle COMMAND_CHANGE_MEDIA_ITEMS");
}
View on GitHub (pinned to dd430f7053)
Solutions
- Override handleSetMediaItems(List<MediaItem> mediaItems, int startIndex, long startPositionMs): replace the playlist, resolve C.INDEX_UNSET / C.TIME_UNSET defaults, and return a future for the resulting State changes.
- If playlist replacement is unsupported, remove COMMAND_SET_MEDIA_ITEM and COMMAND_CHANGE_MEDIA_ITEMS from availableCommands.
- Add an integration test that calls setMediaItem immediately after construction — this error fires on the first such call.
Example fix
// before
// availableCommands includes COMMAND_SET_MEDIA_ITEM, no override:
// after
@Override
protected ListenableFuture<?> handleSetMediaItems(List<MediaItem> mediaItems, int startIndex, long startPositionMs) {
state = new State.Builder()
.setPlaylist(mediaItems)
.setCurrentMediaItemIndex(startIndex == C.INDEX_UNSET ? 0 : startIndex)
.setContentPositionMs(startPositionMs == C.TIME_UNSET ? 0 : startPositionMs)
.build();
invalidateState();
return Futures.immediateVoidFuture();
} Defensive patterns
Strategy: validation
Validate before calling
boolean canSet = player.isCommandAvailable(Player.COMMAND_SET_MEDIA_ITEM)
|| player.isCommandAvailable(Player.COMMAND_CHANGE_MEDIA_ITEMS);
if (canSet) checkOverrides(playerClass, "handleSetMediaItems"); Prevention
- Handle C.INDEX_UNSET and C.TIME_UNSET defaults in startIndex/startPositionMs.
- With only COMMAND_SET_MEDIA_ITEM the list has exactly one item — do not assume arbitrary lists.
- Call invalidateState() (or return work via the future) so listeners see the new playlist.
When it happens
Trigger: Calling player.setMediaItem(item) or setMediaItems(list) on a custom SimpleBasePlayer whose State.availableCommands includes COMMAND_SET_MEDIA_ITEM / COMMAND_CHANGE_MEDIA_ITEMS while handleSetMediaItems is not overridden.
Common situations: Any custom SimpleBasePlayer expected to play content — playlist handling is the first thing implemented, but often the command set is widened before the handler is finished; wrapping MediaController-like sessions where the set commands are forwarded from a remote side.
Related errors
- Missing implementation to handle COMMAND_CHANGE_MEDIA_ITEMS
- Missing implementation to handle COMMAND_SET_VOLUME
- Missing implementation to handle COMMAND_SET_DEVICE_VOLUME o
- Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUM
- Missing implementation to handle COMMAND_SET_VIDEO_SURFACE
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/94ef75062aa5021d.
Report an issue: GitHub.