Skip to content

ArrayIndexOutOfBoundsException in StuckBufferingDetector.update() when switching media on a BUFFERING player #3345

Description

@seokhong-g

Version

Media3 1.10.1

More version details

No response

Devices that reproduce the issue

Reproducible on multiple devices and emulators across Android API 26+.

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

No

Reproduction steps

This crash requires the following conditions to occur simultaneously:

  1. An HLS stream that has been playing long enough to have multiple periods loaded (periodIndex > 0).
  2. The player is in STATE_BUFFERING (e.g., poor network conditions).
  3. setMediaItem() is called on the same player instance to switch to a different media source (e.g., a player pool pattern where players are reused across different content items in a RecyclerView / LazyRow).

These conditions make it difficult to reproduce reliably in isolation, but it occurs consistently in production with a player pool implementation.

Expected result

StuckBufferingDetector.update() should guard against a stale periodIndex when the timeline has changed, rather than propagating an invalid index that causes an ArrayIndexOutOfBoundsException.

Is there a fix planned for an upcoming release? If so, which version can we expect it in?

Actual result

Fatal Exception: java.lang.ArrayIndexOutOfBoundsException: length=1; index=-1
at androidx.media3.exoplayer.PlaylistTimeline.getFirstPeriodIndexByChildIndex (PlaylistTimeline.java:99)
at androidx.media3.exoplayer.AbstractConcatenatedTimeline.getUidOfPeriod (AbstractConcatenatedTimeline.java:262)
at androidx.media3.common.util.StuckPlayerDetector$StuckBufferingDetector.update (StuckPlayerDetector.java:173)
at androidx.media3.common.util.StuckPlayerDetector.onPlayerEvents (StuckPlayerDetector.java:118)
at androidx.media3.common.util.StuckPlayerDetector.access$000 (StuckPlayerDetector.java:34)
at androidx.media3.common.util.StuckPlayerDetector$1.onEvents (StuckPlayerDetector.java:105)
at androidx.media3.exoplayer.ExoPlayerImpl.lambda$new$0 (ExoPlayerImpl.java:320)
at androidx.media3.common.util.ListenerSet$ListenerHolder.iterationFinished (ListenerSet.java:477)
at androidx.media3.common.util.ListenerSet.handleMessage (ListenerSet.java:421)
at android.os.Handler.dispatchMessage (Handler.java:128)
at android.os.Looper.loop (Looper.java:392)
at android.app.ActivityThread.main (ActivityThread.java:10343)

Root cause: ListenerSet delivers player events asynchronously via Handler.sendMessage. BUFFERING events enqueued before setMediaItem() is called are processed after the timeline has already been replaced. StuckBufferingDetector.update() then uses the old periodIndex (valid in the previous HLS multi-period timeline) against the new single-period timeline, causing getChildIndexByPeriodIndex() to return -1, which triggers the crash.

Calling stop() before setMediaItem() does not prevent this — stop() generates a STATE_IDLE event that is queued after the already-enqueued old BUFFERING events.

Additional notes:

  • Crash is on the main thread, dispatched through ListenerSet.handleMessage
  • Frequency is low but consistent in production (player pool with HLS content on slow networks)
  • Partially mitigated by avoiding clearMediaItems() between stop() and setMediaItem(), which eliminates the empty-timeline variant. The multi-period HLS variant remains.
  • This is NOT related to the StuckPlayerException timeout — the crash is in update() which runs on every player event.

Media

Not applicable. The issue is timing-dependent and not related to specific media content. Any HLS stream with multiple periods can trigger this under poor network conditions.

Bug Report

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions