androidx / androidx/media

ArrayIndexOutOfBoundsException in CastTimeline.getWindow when the receiver queue shrinks under RemoteCastPlayer

Open
#3,372 1 comment 0 reactions 2 assignees View on GitHub

@tanay187 is already working on this.

Since Aug 14, 2026.

bug
Dominant language
Java
Stars
3k
Forks
955
Avg merge
12d 14h
Merged PRs (30d)
2

Description

Version

Media3 1.11.0

More version details

androidx.media3:media3-cast:1.11.0, which pulls com.google.android.gms:play-services-cast-framework:22.3.1 transitively. Google Play services on the device: 26.31.31.

Devices that reproduce the issue

ASUS Zenfone 9 (ASUS_AI2201_C), Android 14, SDK 34, build UKQ1.230924.001.WW_Phone-34.0210.0210.276.

Receiver: Chromecast Audio running the Default Media Receiver (CC1AD845).

Devices that do not reproduce the issue

Not established. The trigger is a receiver-side queue change rather than a device characteristic, so I would not expect device dependence.

Reproducible in the demo app?

Not tested

Reproduction steps

The crash needs the receiver queue to shrink while RemoteCastPlayer still holds a current item index that points past the end of the new timeline. In my case a second, non-Media3 sender was joined to the same Default Media Receiver session and was changing the queue concurrently.

  1. Start a Cast session against the Default Media Receiver (CC1AD845) and load a two-item queue through CastPlayer.
  2. Have a second sender join the same receiver application and add an item of its own. Mine was Music Assistant streaming FLAC from http://<host>:8097/...; any sender requesting CC1AD845 joins the session and shares the queue.
  3. Let the first item play to its end so the receiver advances and drops the finished item.

Three queue operations are rejected by the receiver shortly before the crash:

07:51:32 W/MediaControlChannel: received unexpected error: Invalid Request.
07:51:32 W/MediaControlChannel: Possibility of local queue out of sync with receiver queue.
                                Refetching sequence number. Current Local Sequence Number = 6
07:51:35 W/MediaControlChannel: received unexpected error: Invalid Request.
07:52:09 W/MediaControlChannel: received unexpected error: Invalid Request.
07:52:09 E/AndroidRuntime: FATAL EXCEPTION: main

The crash lands 127 ms after the third rejection.

Expected result

RemoteCastPlayer survives a receiver queue change that invalidates the current item index. A queue shrinking underneath the player is a normal condition once more than one sender is attached to the Default Media Receiver, and it is a condition the library already accounts for elsewhere: CastTimelineTracker.getCastTimeline substitutes UNKNOWN_CONTENT_ID when MediaQueueItem.getMedia() returns null.

Actual result

ArrayIndexOutOfBoundsException on the main thread, thrown from inside a Cast SDK callback, which kills the process.

FATAL EXCEPTION: main
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
	at androidx.media3.cast.CastTimeline.getWindow(CastTimeline.java:156)
	at androidx.media3.common.Timeline.getWindow(Timeline.java:1158)
	at androidx.media3.common.BasePlayer.isCurrentMediaItemSeekable(BasePlayer.java:389)
	at androidx.media3.common.util.Util.getAvailableCommands(Util.java:4102)
	at androidx.media3.cast.RemoteCastPlayer.updateAvailableCommandsAndNotifyIfChanged(RemoteCastPlayer.java:1549)
	at androidx.media3.cast.RemoteCastPlayer.updateTimelineAndNotifyIfChanged(RemoteCastPlayer.java:1400)
	at androidx.media3.cast.RemoteCastPlayer.access$2000(RemoteCastPlayer.java:112)
	at androidx.media3.cast.RemoteCastPlayer$MediaQueueCallback.mediaQueueChanged(RemoteCastPlayer.java:2197)
	at com.google.android.gms.cast.framework.media.MediaQueue.zzw(play-services-cast-framework@@22.3.1:3)
	at com.google.android.gms.cast.framework.media.MediaQueue.zzi(play-services-cast-framework@@22.3.1:0)
	at com.google.android.gms.cast.framework.media.zzn.zze(play-services-cast-framework@@22.3.1:14)
	at com.google.android.gms.cast.framework.media.zzbe.zzj(play-services-cast-framework@@22.3.1:2)
	at com.google.android.gms.cast.internal.zzar.zzL(play-services-cast@@22.3.1:35)
	at com.google.android.gms.cast.framework.media.RemoteMediaClient.onMessageReceived(play-services-cast-framework@@22.3.1:1)
	at com.google.android.gms.cast.zzbj.run(play-services-cast@@22.3.1:4)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:245)
	at android.os.Looper.loop(Looper.java:364)
	at android.app.ActivityThread.main(ActivityThread.java:8439)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:977)

Reading the frames: updateTimelineAndNotifyIfChanged installs the new one-window timeline and then calls updateAvailableCommandsAndNotifyIfChanged, which goes through Util.getAvailableCommands into isCurrentMediaItemSeekable() and therefore getWindow(getCurrentMediaItemIndex()). The index is still 1 from the previous two-item timeline, so it reads past the end of the array. The available-commands recalculation appears to run before the current index has been reconciled with the timeline it is being evaluated against.

This looks like the same class of defect as google/ExoPlayer#4168, where getCurrentWindowIndex() kept returning a stale value for a while after new media sources were set.

I searched the tracker for CastTimeline together with ArrayIndexOutOfBoundsException and found nothing matching this stack.

Media

Any two audio items reproduce it, since the crash is driven by the queue transition rather than by the content. The queue in my capture held one MP3 (audio/mpeg, about 2 h 32 min) plus the FLAC live stream added by the other sender.

I have the full logcat covering the minutes around the crash, including the receiver MEDIA_STATUS payload that shows both queue items. Happy to email it if that helps.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.