google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_SET_SHUFFLE_MODE

Error message

Missing implementation to handle COMMAND_SET_SHUFFLE_MODE

What it means

Default handler for Player.setShuffleModeEnabled(...) in SimpleBasePlayer: throws IllegalStateException when COMMAND_SET_SHUFFLE_MODE is available but the subclass did not implement handleSetShuffleModeEnabled(boolean).

Source

Thrown at library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java:2994

   *     changes caused by this call.
   */
  @ForOverride
  protected ListenableFuture<?> handleSetRepeatMode(@RepeatMode int repeatMode) {
    throw new IllegalStateException("Missing implementation to handle COMMAND_SET_REPEAT_MODE");
  }

  /**
   * Handles calls to {@link Player#setShuffleModeEnabled}.
   *
   * <p>Will only be called if {@link Player#COMMAND_SET_SHUFFLE_MODE} is available.
   *
   * @param shuffleModeEnabled Whether shuffle mode was requested to be enabled.
   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     changes caused by this call.
   */
  @ForOverride
  protected ListenableFuture<?> handleSetShuffleModeEnabled(boolean shuffleModeEnabled) {
    throw new IllegalStateException("Missing implementation to handle COMMAND_SET_SHUFFLE_MODE");
  }

  /**
   * Handles calls to {@link Player#setPlaybackParameters} or {@link Player#setPlaybackSpeed}.
   *
   * <p>Will only be called if {@link Player#COMMAND_SET_SPEED_AND_PITCH} is available.
   *
   * @param playbackParameters The requested {@link PlaybackParameters}.
   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     changes caused by this call.
   */
  @ForOverride
  protected ListenableFuture<?> handleSetPlaybackParameters(PlaybackParameters playbackParameters) {
    throw new IllegalStateException("Missing implementation to handle COMMAND_SET_SPEED_AND_PITCH");
  }

  /**
   * Handles calls to {@link Player#setTrackSelectionParameters}.

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override handleSetShuffleModeEnabled(boolean) to store the flag and recalc window indices, returning the future from updateStateAndNotify.
  2. Or drop COMMAND_SET_SHUFFLE_MODE from availableCommands so the toggle is hidden/disabled in connected controllers.
  3. If implementing shuffle, also implement the index-resolution logic (getNextMediaItemIndex) that honors it.

Example fix

// before
// no override; session controller enables shuffle -> throws

// after
@Override
protected ListenableFuture<?> handleSetShuffleModeEnabled(boolean shuffleModeEnabled) {
  return updateStateAndNotify(state.buildUpon().setShuffleModeEnabled(shuffleModeEnabled).build());
}
Defensive patterns

Strategy: validation

Validate before calling

if (!supportsShuffle) commands.remove(Player.COMMAND_SET_SHUFFLE_MODE);

Prevention

When it happens

Trigger: player.setShuffleModeEnabled(true) — often issued by a MediaController/UI shuffle button — against a SimpleBasePlayer subclass missing the override while its State includes COMMAND_SET_SHUFFLE_MODE.

Common situations: Custom players wired into a MediaSession; shuffle toggles from Android Auto/system UI reaching an incompletely implemented player.

Related errors


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/e592b59ca157fc43. Report an issue: GitHub.