google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_PREPARE

Error message

Missing implementation to handle COMMAND_PREPARE

What it means

Default handler for Player.prepare() in SimpleBasePlayer: it throws IllegalStateException because the subclass did not override handlePrepare(), while the current State advertises COMMAND_PREPARE. SimpleBasePlayer intentionally fails fast on unimplemented command handlers rather than silently no-op'ing.

Source

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

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

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

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override handlePrepare() to trigger your backend's prepare and return a future completed when the state update lands.
  2. Or exclude COMMAND_PREPARE from the State's available commands if preparation is not a meaningful operation for your player.
  3. Add a test asserting each advertised command either has an override or is excluded.

Example fix

// before
// subclass relies on default commands, no handlePrepare

// after
@Override
protected ListenableFuture<?> handlePrepare() {
  backend.prepare();
  return updateStateAndNotify(state.buildUpon().setPlaybackState(STATE_BUFFERING).build());
}
Defensive patterns

Strategy: validation

Validate before calling

// In your State construction:
if (!supportsPrepare) commands.remove(Player.COMMAND_PREPARE);

Prevention

When it happens

Trigger: Calling player.prepare() on a SimpleBasePlayer subclass whose State includes COMMAND_PREPARE in availableCommands but which does not override handlePrepare().

Common situations: Custom player implementations (e.g. casting to a third-party backend) that keep the default full command set; migrating an implementation onto SimpleBasePlayer and missing one handler.

Related errors


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