google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_SET_DEVICE_VOLUME o

Error message

Missing implementation to handle COMMAND_SET_DEVICE_VOLUME or COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS

What it means

SimpleBasePlayer routes Player.setDeviceVolume(int) and setDeviceVolume(int, int) to handleSetDeviceVolume(int, int). The default implementation throws IllegalStateException when the subclass declares Player.COMMAND_SET_DEVICE_VOLUME or Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS in availableCommands without overriding the handler. It is a command-advertisement/handler mismatch, not a device failure.

Source

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

    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(
        "Missing implementation to handle COMMAND_SET_DEVICE_VOLUME or"
            + " COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS");
  }

  /**
   * Handles calls to {@link Player#increaseDeviceVolume()} and {@link
   * Player#increaseDeviceVolume(int)}.
   *
   * <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} or {@link
   * Player#COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} is available.
   *
   * @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<?> handleIncreaseDeviceVolume(@C.VolumeFlags int flags) {
    throw new IllegalStateException(

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override handleSetDeviceVolume(int deviceVolume, int flags) in the subclass, applying the device volume (e.g. via AudioManager) and returning a completed ListenableFuture.
  2. If device volume cannot be controlled, do not include COMMAND_SET_DEVICE_VOLUME / COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS in availableCommands.
  3. Write a unit test that iterates every advertised command and invokes the corresponding Player method to catch unimplemented handlers early.

Example fix

// before
// availableCommands includes COMMAND_SET_DEVICE_VOLUME but no override:

// after
@Override
protected ListenableFuture<?> handleSetDeviceVolume(int deviceVolume, int flags) {
  audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, deviceVolume, flags);
  return Futures.immediateVoidFuture();
}
Defensive patterns

Strategy: validation

Validate before calling

if (player.getState().availableCommands.contains(Player.COMMAND_SET_DEVICE_VOLUME)
    || player.getState().availableCommands.contains(Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)) {
  checkOverrides(playerClass, "handleSetDeviceVolume");
}

Prevention

When it happens

Trigger: Calling player.setDeviceVolume(...) on a custom SimpleBasePlayer whose State.availableCommands contains COMMAND_SET_DEVICE_VOLUME or COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS while handleSetDeviceVolume is not overridden.

Common situations: Reusing a broad command set from an existing player implementation when wrapping a remote or platform player; upgrading Media3 versions where the flags variant was introduced and the command list was widened without adding the handler.

Related errors


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