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
- Override protected ListenableFuture<?> handleSetVolume(float volume) in your SimpleBasePlayer subclass and apply the volume, returning immediateFuture(null) or a future for async work.
- 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.
- 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
- Start from the smallest availableCommands set and add commands only as you implement each handle* method.
- Write a reflection-based test that maps every COMMAND_* constant to its handle* method and asserts an override exists when the command is advertised.
- Do not copy Player.Commands.DEFAULT blindly; it includes commands whose handlers you may not have written.
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
- 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
- Missing implementation to handle COMMAND_SET_MEDIA_ITEM(S)
- Missing implementation to handle COMMAND_CHANGE_MEDIA_ITEMS
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/8b0c9bc9d9ede112.
Report an issue: GitHub.