google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_SET_REPEAT_MODE

Error message

Missing implementation to handle COMMAND_SET_REPEAT_MODE

What it means

Default handler for Player.setRepeatMode(...) in SimpleBasePlayer throws when handleSetRepeatMode is missing while COMMAND_SET_REPEAT_MODE is advertised. The base class enforces the one-handler-per-available-command contract by failing fast.

Source

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

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

  /**
   * Handles calls to {@link Player#setRepeatMode}.
   *
   * <p>Will only be called if {@link Player#COMMAND_SET_REPEAT_MODE} is available.
   *
   * @param repeatMode The requested {@link RepeatMode}.
   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     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}.

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override handleSetRepeatMode(int repeatMode), persist it in your state, and return the state-update future.
  2. If repeat is unsupported, build your State without COMMAND_SET_REPEAT_MODE so Player.setRepeatMode becomes a no-op for callers.
  3. Remember repeat mode interacts with getNextMediaItemIndex logic — implement both consistently.

Example fix

// before
// no override; controller calls setRepeatMode(REPEAT_MODE_ALL) -> throws

// after
@Override
protected ListenableFuture<?> handleSetRepeatMode(@RepeatMode int repeatMode) {
  return updateStateAndNotify(state.buildUpon().setRepeatMode(repeatMode).build());
}
Defensive patterns

Strategy: validation

Validate before calling

if (!supportsRepeat) commands.remove(Player.COMMAND_SET_REPEAT_MODE);

Prevention

When it happens

Trigger: player.setRepeatMode(Player.REPEAT_MODE_ALL) (e.g. from a UI toggle or a media controller) on a SimpleBasePlayer subclass that did not override handleSetRepeatMode but left COMMAND_SET_REPEAT_MODE in its State.

Common situations: Custom players that do not support repeat but copy the default command set; UI controllers that automatically call setRepeatMode on player connection.

Related errors


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