google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_SET_VOLUME

Error message

Missing implementation to handle COMMAND_SET_VOLUME

What it means

SimpleBasePlayer is an abstract base class that delegates every Player call to a protected handle* method. If a subclass advertises Player.COMMAND_SET_VOLUME in getState().availableCommands but does not override handleSetVolume(float), the default implementation throws this IllegalStateException as soon as Player.setVolume is called. The error therefore signals a contract violation between the declared available commands and the implemented handlers.

Source

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

  @ForOverride
  protected ListenableFuture<?> handleSetPlaylistMetadata(MediaMetadata playlistMetadata) {
    throw new IllegalStateException(
        "Missing implementation to handle COMMAND_SET_PLAYLIST_METADATA");
  }

  /**
   * Handles calls to {@link Player#setVolume}.
   *
   * <p>Will only be called if {@link Player#COMMAND_SET_VOLUME} is available.
   *
   * @param volume The requested audio volume, with 0 being silence and 1 being unity gain (signal
   *     unchanged).
   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     changes caused by this call.
   */
  @ForOverride
  protected ListenableFuture<?> handleSetVolume(@FloatRange(from = 0, to = 1.0) float volume) {
    throw new IllegalStateException("Missing implementation to handle COMMAND_SET_VOLUME");
  }

  /**
   * Handles calls to {@link Player#setDeviceVolume(int)} and {@link Player#setDeviceVolume(int,
   * int)}.
   *
   * <p>Will only be called if {@link Player#COMMAND_SET_DEVICE_VOLUME} or {@link
   * Player#COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS} is available.
   *
   * @param deviceVolume The requested device volume.
   * @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     changes caused by this call.
   */
  @ForOverride
  protected ListenableFuture<?> handleSetDeviceVolume(
      @IntRange(from = 0) int deviceVolume, int flags) {
    throw new IllegalStateException(

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override protected ListenableFuture<?> handleSetVolume(float volume) in your SimpleBasePlayer subclass and apply the volume, returning immediateFuture(null) or a future for async work.
  2. If volume control is not supported, remove Player.COMMAND_SET_VOLUME from the availableCommands in the State returned by getState(), so Player.setVolume becomes a no-op instead of throwing.
  3. Audit all handle* methods against every command you declare in availableCommands; each advertised command must have a matching override.

Example fix

// before
setState(new State.Builder().setAvailableCommands(new Player.Commands.Builder().add(Player.COMMAND_SET_VOLUME).build())...build());
// handleSetVolume not overridden -> IllegalStateException on setVolume()

// after
@Override
protected ListenableFuture<?> handleSetVolume(float volume) {
  state = state.buildUpon().setVolume(volume).build();
  return Futures.immediateVoidFuture();
}
Defensive patterns

Strategy: validation

Validate before calling

// Before exposing the player, assert every advertised command has a handler.
Player.Commands cmds = player.getState().availableCommands;
if (cmds.contains(Player.COMMAND_SET_VOLUME)
    && !overridesHandler(playerClass, "handleSetVolume")) {
  throw new IllegalStateException("COMMAND_SET_VOLUME advertised but handleSetVolume missing");
}

Prevention

When it happens

Trigger: Calling player.setVolume(...) on a custom SimpleBasePlayer subclass whose State built with State.Builder.setAvailableCommands(...) includes Player.COMMAND_SET_VOLUME, while handleSetVolume was never overridden.

Common situations: Building a custom player on top of SimpleBasePlayer and copying a large availableCommands set (e.g. from Player.Commands.DEFAULT or another player) without implementing every corresponding handler; adding volume support to availableCommands before writing the handler.

Related errors


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