You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Seems to be happening across a wide variety of devices and android versions (Samsung, Redmi, Oppo, Sony, Motorozola devices on Android versions 10,11,12,13, and 15)
Devices that do not reproduce the issue
Unknown
Reproducible in the demo app?
No
Reproduction steps
Unfortunately I don't have repro steps
Expected result
The app doesn't crash
Actual result
The app crashes with the following stack trace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.media3.exoplayer.hls.n.c()' on a null object reference
at androidx.media3.exoplayer.hls.HlsSampleStreamWrapper.mapSampleQueuesToMatchTrackGroups(HlsSampleStreamWrapper.java:1370)
at androidx.media3.exoplayer.hls.HlsSampleStreamWrapper.maybeFinishPrepare(HlsSampleStreamWrapper.java:1344)
at androidx.media3.exoplayer.hls.HlsSampleStreamWrapper.$r8$lambda$UK4TNmzu4rF7l558xzg8C7fYdDI(HlsSampleStreamWrapper.java:0)
at androidx.media3.exoplayer.hls.HlsSampleStreamWrapper$$ExternalSyntheticLambda1.run(HlsSampleStreamWrapper:0)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
Media
Seems to only be happening for HLS streams but I can't point to any specific media.
From manually looking at the mapping file (not sure why our crash reporting tool isn't de-obfuscating), I can confirm that hls.n is exoplayer.hls.HlsSampleStream and c is bindSampleQueue...
One thing I want to note is it seems like this only started appearing after we started relying on the media3 preload manager and the media3 downloading support. I don't see why either of those things would have an impact but I wanted to throw it out there.
Looking at the code I also don't see how this is possible, but it's happening a large amount - it's not like only one crash popping up; it's our top crash ATM.
One thing I want to note is it seems like this only started appearing after we started relying on the media3 preload manager and the media3 downloading support. I don't see why either of those things would have an impact but I wanted to throw it out there.
Following this clue - can you give a bit of info about how you set up the preload manager? Does it share the same looper as ExoPlayer.getPlaybackLooper?
I work with @alexsullivan-substack and set up the PreloadManager. I'm using it with as little configuration as was needed to get it working. It's created via:
@tianyif I am not longer seeing the NPE exception, but now am seeing this one as our top crasher.
java.lang.IllegalStateException: null
at androidx.media3.common.util.Assertions.checkStateNotNull(Contexts.java:117)
at androidx.media3.exoplayer.trackselection.TrackSelector.getBandwidthMeter(TrackSelector.java:253)
at androidx.media3.exoplayer.trackselection.DefaultTrackSelector.selectTracks(DefaultTrackSelector.java:2631)
at androidx.media3.exoplayer.trackselection.MappingTrackSelector.selectTracks(MappingTrackSelector.java:429)
at androidx.media3.exoplayer.source.preload.PreloadMediaSource$PreloadMediaPeriodCallback.lambda$onPrepared$0(PreloadMediaSource.java:480)
at t1.PreloadMediaSource$PreloadMediaPeriodCallback$$ExternalSyntheticLambda0.run(PreloadMediaSource:0)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.os.HandlerThread.run(HandlerThread.java:67)
@tianyif I am not calling setTrackSelectorFactory(). I am releasing the DefaultPreloadManager only upon leaving the app (via onCleared() of a ViewModel that is scoped to the Activity in a single-Activity application.
One thing that I just noticed, however, is that I am removing media from the PreloadManager immediately before releasing the player that is using it. I suspect the order of these operation may be to blame. What do you think?
The exception happens when PreloadMediaSource tries to select tracks after the track selector is released.
If setTrackSelectorFactory is not called, the DefaultPreloadManager and ExoPlayer will use DefaultTrackSelector but in different instances (the library guarantees that), which means that even the player releases its TrackSelector, the one in DefaultPreloadManager (in PreloadMediaSource) shouldn't be released. At this point, I don't think the order of removing media from preload manager and releasing the player matters.
One possible reason is that the period triggers onPrepared after the DefaultPreloadManager is released. In theory, this shouldn't happen as we will release all the sources and its holding PreloadMediaPeriodbefore releasing DefaultPreloadManager (where its TrackSelector is released), all this operations are already on preload looper. But things can still go wrong if we failed to prevent onPrepared to be triggered after content period is released.
Did you observe this issue only from specific stream (eg. HLS)?
@tianyif All our streams are HLS. I have not been able to replicate this error myself. I am only seeing it in our crash logs. It doesn't appear to be specific to any particular stream.
@tianyif I was able to repro the crash for the first time. It occurred about 1/2 second after staring to play a video. When I returned to the app and replayed the same video there was no error. I will keep an eye out for it happening again, to see if there are any patterns that I can see when it happens.
java.lang.IllegalStateException: null
at androidx.media3.common.util.Assertions.checkStateNotNull(RoundRect.kt:117)
at androidx.media3.exoplayer.trackselection.TrackSelector.getBandwidthMeter(TrackSelector.java:253)
at androidx.media3.exoplayer.trackselection.DefaultTrackSelector.selectTracks(DefaultTrackSelector.java:2631)
at androidx.media3.exoplayer.trackselection.MappingTrackSelector.selectTracks(MappingTrackSelector.java:429)
at androidx.media3.exoplayer.source.preload.PreloadMediaSource$PreloadMediaPeriodCallback.lambda$onPrepared$0(PreloadMediaSource.java:480)
at t1.PreloadMediaSource$PreloadMediaPeriodCallback$$ExternalSyntheticLambda0.run(PreloadMediaSource:0)
at android.os.Handler.handleCallback(Handler.java:991)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:232)
at android.os.Looper.loop(Looper.java:317)
at android.os.HandlerThread.run(HandlerThread.java:85)
It occurred about 1/2 second after staring to play a video.
So when you reproduced this issue, there hasn't been a chance that DefaultPreloadManager.release is called? Interesting, as for now the only suspicious direction that I felt is around releasing the preload manager. But I'll go ahead to verify the case in my mind first and fix it if it is valid.
@tianyif I found the issue! You were right that the DefaultPreloadManager.release is called. I was confused due to the scope of an injected dependency. I figured out a path to reproduce the crash reliably, and so can implement a fix. Thank you very much for your help with it.
Thanks for the update! Could you please explain the step of reproducing and where you call DefaultPreloadManager.release that introducing this issue? Just need to see if there is anything from the library should fix, if it's some corner case we also missed.
@tianyif Sure. The problem is related to my architecture and lifecycle. I have a PlayerManager class that is injected into a ViewModel. The VM gets instances of ExoPlayer and DefaultPreloadManager from the PlayerManger. The VM was also releasing the DefaultPreloadManager in onCleared which in itself was fine. The problem is that PlayerManager is injected as a singleton, and it is also injected into a Service. The crash happens if I exit the UI of the application while the service is running and return to the UI while the service continues to run. In this case, the VM would receive the same instance of PlayerManager which would provide the same instance of DefaultPreloadManager that it provided before... which has already been released. So then as soon as I tried playing anything, it crashes.
Activity
icbaker commentedon Jun 2, 2025
Are you able to retrace the error, to deobfuscate the
androidx.media3.exoplayer.hls.n.c()symbol?HlsSampleStreamWrapper.java:1370is this at version 1.6.1:media/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsSampleStreamWrapper.java
Lines 1369 to 1371 in ae9a233
So the error suggests that the
this.hlsSampleStreamslist contains a null element.hlsSampleStreamsis only added to in one place, and only non-null entries are added:media/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsSampleStreamWrapper.java
Lines 1270 to 1274 in ae9a233
So looking just at the code - this NPE looks like it should be impossible...
alexsullivan-substack commentedon Jun 2, 2025
From manually looking at the mapping file (not sure why our crash reporting tool isn't de-obfuscating), I can confirm that
hls.nisexoplayer.hls.HlsSampleStreamandcisbindSampleQueue...alexsullivan-substack commentedon Jun 2, 2025
One thing I want to note is it seems like this only started appearing after we started relying on the media3 preload manager and the media3 downloading support. I don't see why either of those things would have an impact but I wanted to throw it out there.
Looking at the code I also don't see how this is possible, but it's happening a large amount - it's not like only one crash popping up; it's our top crash ATM.
icbaker commentedon Jun 3, 2025
Following this clue - can you give a bit of info about how you set up the preload manager? Does it share the same looper as
ExoPlayer.getPlaybackLooper?wongcain commentedon Jun 3, 2025
I work with @alexsullivan-substack and set up the PreloadManager. I'm using it with as little configuration as was needed to get it working. It's created via:
I am also using the
DefaultPreloadManager.Builderto configure ExoPlayer instances like so:tianyif commentedon Jun 3, 2025
@wongcain, quick check - do the
DefaultPreloadManagerand theExoPlayerare built from the sameDefaultPreloadManager.Builderinstance?2 remaining items
wongcain commentedon Jun 3, 2025
@tianyif Thank you! I will get a new app version with this change out asap and report back.
wongcain commentedon Jun 9, 2025
@tianyif I am not longer seeing the NPE exception, but now am seeing this one as our top crasher.
Any tips on how to resolve?
tianyif commentedon Jun 9, 2025
@wongcain,
Did you set a custom
TrackSelector.FactoryviaDefaultPreloadManager.Builder?media/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/preload/DefaultPreloadManager.java
Line 147 in ae9a233
If yes, could you paste what's the custom
TrackSelector.Factorylike?Or, when did you release the
DefaultPreloadManager?wongcain commentedon Jun 9, 2025
@tianyif I am not calling
setTrackSelectorFactory(). I am releasing theDefaultPreloadManageronly upon leaving the app (viaonCleared()of aViewModelthat is scoped to theActivityin a single-Activity application.One thing that I just noticed, however, is that I am removing media from the PreloadManager immediately before releasing the player that is using it. I suspect the order of these operation may be to blame. What do you think?
tianyif commentedon Jun 9, 2025
@wongcain,
The exception happens when
PreloadMediaSourcetries to select tracks after the track selector is released.If
setTrackSelectorFactoryis not called, theDefaultPreloadManagerandExoPlayerwill useDefaultTrackSelectorbut in different instances (the library guarantees that), which means that even the player releases itsTrackSelector, the one inDefaultPreloadManager(inPreloadMediaSource) shouldn't be released. At this point, I don't think the order of removing media from preload manager and releasing the player matters.One possible reason is that the period triggers
onPreparedafter theDefaultPreloadManageris released. In theory, this shouldn't happen as we will release all the sources and its holdingPreloadMediaPeriodbefore releasingDefaultPreloadManager(where itsTrackSelectoris released), all this operations are already on preload looper. But things can still go wrong if we failed to preventonPreparedto be triggered after content period is released.Did you observe this issue only from specific stream (eg. HLS)?
wongcain commentedon Jun 9, 2025
@tianyif All our streams are HLS. I have not been able to replicate this error myself. I am only seeing it in our crash logs. It doesn't appear to be specific to any particular stream.
wongcain commentedon Jun 9, 2025
@tianyif I was able to repro the crash for the first time. It occurred about 1/2 second after staring to play a video. When I returned to the app and replayed the same video there was no error. I will keep an eye out for it happening again, to see if there are any patterns that I can see when it happens.
wongcain commentedon Jun 9, 2025
Fwiw, the stack trace was slightly different:
tianyif commentedon Jun 10, 2025
@wongcain,
So when you reproduced this issue, there hasn't been a chance that
DefaultPreloadManager.releaseis called? Interesting, as for now the only suspicious direction that I felt is around releasing the preload manager. But I'll go ahead to verify the case in my mind first and fix it if it is valid.wongcain commentedon Jun 10, 2025
@tianyif I found the issue! You were right that the
DefaultPreloadManager.releaseis called. I was confused due to the scope of an injected dependency. I figured out a path to reproduce the crash reliably, and so can implement a fix. Thank you very much for your help with it.tianyif commentedon Jun 10, 2025
@wongcain,
Thanks for the update! Could you please explain the step of reproducing and where you call
DefaultPreloadManager.releasethat introducing this issue? Just need to see if there is anything from the library should fix, if it's some corner case we also missed.wongcain commentedon Jun 10, 2025
@tianyif Sure. The problem is related to my architecture and lifecycle. I have a
PlayerManagerclass that is injected into a ViewModel. The VM gets instances ofExoPlayerandDefaultPreloadManagerfrom thePlayerManger. The VM was also releasing theDefaultPreloadManagerinonClearedwhich in itself was fine. The problem is thatPlayerManageris injected as a singleton, and it is also injected into aService. The crash happens if I exit the UI of the application while the service is running and return to the UI while the service continues to run. In this case, the VM would receive the same instance ofPlayerManagerwhich would provide the same instance ofDefaultPreloadManagerthat it provided before... which has already been released. So then as soon as I tried playing anything, it crashes.tianyif commentedon Jun 12, 2025
Also manually linking the commit 4811418 here, which signals the thread inconsistency early and informatively (addressing the initial problem).