google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_STOP

Error message

Missing implementation to handle COMMAND_STOP

What it means

Default handler for Player.stop() in SimpleBasePlayer throws when the subclass neither overrides handleStop() nor removes COMMAND_STOP from the advertised commands. SimpleBasePlayer requires every available command to have a concrete handler.

Source

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

   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     changes caused by this call.
   */
  @ForOverride
  protected ListenableFuture<?> handlePrepare() {
    throw new IllegalStateException("Missing implementation to handle COMMAND_PREPARE");
  }

  /**
   * Handles calls to {@link Player#stop}.
   *
   * <p>Will only be called if {@link Player#COMMAND_STOP} is available.
   *
   * @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}.
   *

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override handleStop(): transition state to STATE_IDLE and clear the playlist (or reflect your backend's stop), returning the state-update future.
  2. If stop is unsupported, remove COMMAND_STOP from the State's availableCommands.
  3. Wire the override to also release backend resources so subsequent release() is cheap.

Example fix

// before
// no handleStop override; player.stop() throws

// after
@Override
protected ListenableFuture<?> handleStop() {
  backend.stop();
  return updateStateAndNotify(
      new State.Builder().setPlaybackState(STATE_IDLE).setPlaylist(Collections.emptyList()).build());
}
Defensive patterns

Strategy: validation

Validate before calling

if (!supportsStop) commands.remove(Player.COMMAND_STOP);

Prevention

When it happens

Trigger: player.stop() (or stop with reset) is invoked on a SimpleBasePlayer subclass whose availableCommands include COMMAND_STOP while handleStop() is not implemented.

Common situations: Custom players built on SimpleBasePlayer with default command availability; integration code that calls stop() during teardown hitting an unfinished implementation.

Related errors


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