google/ExoPlayer · error · IllegalStateException
Missing implementation to handle COMMAND_RELEASE
Error message
Missing implementation to handle COMMAND_RELEASE
What it means
Default handler for Player.release() in SimpleBasePlayer: IllegalStateException thrown because handleRelease() is not overridden although COMMAND_RELEASE is available in the current State. Every command the player advertises must be backed by an implementation.
Source
Thrown at library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java:2966
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleStop() {
throw new IllegalStateException("Missing implementation to handle COMMAND_STOP");
}
/**
* Handles calls to {@link Player#release}.
*
* <p>Will only be called if {@link Player#COMMAND_RELEASE} is available.
*
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* 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}.View on GitHub (pinned to dd430f7053)
Solutions
- Override handleRelease() to tear down your backend and return a future completed when fully released; also set STATE_IDLE per the documented contract.
- Alternatively remove COMMAND_RELEASE from availableCommands — but note most clients unconditionally call release(), so implementing it is usually correct.
- Make handleRelease idempotent so double-release does not fail.
Example fix
// before
// subclass without handleRelease -> player.release() throws
// after
@Override
protected ListenableFuture<?> handleRelease() {
backend.shutdown();
return updateStateAndNotify(
new State.Builder().setPlaybackState(STATE_IDLE).setPlaylist(Collections.emptyList()).build());
} Defensive patterns
Strategy: validation
Validate before calling
if (!supportsRelease) commands.remove(Player.COMMAND_RELEASE); // rarely correct — most clients call release()
Prevention
- Always implement handleRelease() when exposing a SimpleBasePlayer.
- Make release idempotent and set STATE_IDLE.
- Call player.release() in unit tests of your custom player.
When it happens
Trigger: Calling player.release() on a SimpleBasePlayer subclass that did not override handleRelease() while its State includes COMMAND_RELEASE.
Common situations: Custom player implementations that clean up resources elsewhere (e.g. in a close() method) but forget the handler; test harnesses that always call release().
Related errors
- Missing implementation to handle COMMAND_PLAY_PAUSE
- Missing implementation to handle COMMAND_PREPARE
- Missing implementation to handle COMMAND_STOP
- Missing implementation to handle COMMAND_SET_REPEAT_MODE
- Missing implementation to handle COMMAND_SET_SHUFFLE_MODE
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/34032f4d59617fca.
Report an issue: GitHub.