google/ExoPlayer · error · IllegalStateException

Missing implementation to handle COMMAND_SET_PLAYLIST_METADA

Error message

Missing implementation to handle COMMAND_SET_PLAYLIST_METADATA

What it means

Default handler for Player.setPlaylistMetadata(...) in SimpleBasePlayer: throws IllegalStateException because COMMAND_SET_PLAYLIST_METADATA is advertised but the subclass did not override handleSetPlaylistMetadata(MediaMetadata).

Source

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

  @ForOverride
  protected ListenableFuture<?> handleSetTrackSelectionParameters(
      TrackSelectionParameters trackSelectionParameters) {
    throw new IllegalStateException(
        "Missing implementation to handle COMMAND_SET_TRACK_SELECTION_PARAMETERS");
  }

  /**
   * Handles calls to {@link Player#setPlaylistMetadata}.
   *
   * <p>Will only be called if {@link Player#COMMAND_SET_PLAYLIST_METADATA} is available.
   *
   * @param playlistMetadata The requested {@linkplain MediaMetadata playlist metadata}.
   * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
   *     changes caused by this call.
   */
  @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");
  }

View on GitHub (pinned to dd430f7053)

Solutions

  1. Override handleSetPlaylistMetadata(MediaMetadata playlistMetadata) and store it in the State: state.buildUpon().setPlaylistMetadata(metadata).build().
  2. Or exclude COMMAND_SET_PLAYLIST_METADATA from availableCommands if playlist metadata is owned solely by the app.
  3. Notify connected controllers through the returned state-update future so UI stays consistent.

Example fix

// before
// no override; controller updates playlist title -> throws

// after
@Override
protected ListenableFuture<?> handleSetPlaylistMetadata(MediaMetadata playlistMetadata) {
  return updateStateAndNotify(
      state.buildUpon().setPlaylistMetadata(playlistMetadata).build());
}
Defensive patterns

Strategy: validation

Validate before calling

if (!supportsPlaylistMetadataEdit) commands.remove(Player.COMMAND_SET_PLAYLIST_METADATA);

Prevention

When it happens

Trigger: player.setPlaylistMetadata(mediaMetadata) — e.g. a library app updating the playlist title shown by a MediaController — against a SimpleBasePlayer subclass whose State includes the command without an override.

Common situations: Custom queue implementations exposed through MediaSession; UI or controller code updating playlist metadata on players that never implemented it.

Related errors


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