Skip to content

fix: ImagesData.firstOrNull throws RangeError on empty backDrop list#979

Closed
Beary-Handsome wants to merge 2 commits intoDonutWare:developfrom
Beary-Handsome:fix/imagesdata-firstornull-empty-list
Closed

fix: ImagesData.firstOrNull throws RangeError on empty backDrop list#979
Beary-Handsome wants to merge 2 commits intoDonutWare:developfrom
Beary-Handsome:fix/imagesdata-firstornull-empty-list

Conversation

@Beary-Handsome
Copy link
Copy Markdown

What

Replace backDrop?[0] with backDrop?.firstOrNull (from package:collection, already imported in this file).

   ImageData? get firstOrNull {
-    return primary ?? backDrop?[0];
+    return primary ?? backDrop?.firstOrNull;
   }

Why

When primary is null AND backDrop is an empty list (rather than null) — which happens for any Jellyfin item whose backdropImageTags is []backDrop?[0] indexes an empty list and throws:

RangeError (length): Invalid value: Valid value range is empty: 0

The getter is named firstOrNull but the implementation didn't actually handle the empty-list case. package:collection's firstOrNull extension has the correct semantics.

Symptom this fixes

In MediaControlsWrapper.play, playBackItem.images?.firstOrNull is evaluated synchronously. The unhandled RangeError escapes through the await state.play() chain in VideoPlayerNotifier.loadPlaybackItem and aborts video pipeline init. Audio that was already buffered keeps playing, but the video stream never starts decoding — externally this looks like "audio works but video keeps loading forever."

Reproducible on any non-Windows/non-Web build (i.e. Linux desktop, Android, iOS, macOS) playing an item where Jellyfin returns no backdrop images. The most reliable triggers are .strm-backed Episode items (e.g. content fed through a Usenet/Easynews bridge) — these typically have minimal Jellyfin metadata and no backdrop array — but any Episode/Movie with backdropImageTags: [] and no primary image is affected.

Likely related: #57, #159, #215, #429 — all reported the symptom (playback hang on streamed/.strm content) but never landed on the root cause.

How to reproduce

  1. Set up a Jellyfin library where some items have backdropImageTags: [] and a missing/null primary image. (Or run any Easynews-style .strm bridge.)
  2. Build a non-Windows Fladder.
  3. Play one of those items. Audio plays, video stays in "loading" indefinitely. Run from terminal and you'll see Unhandled Exception: RangeError (length) in stderr.

After this patch: the getter correctly returns null on empty, the synchronous evaluation no longer throws, and playback proceeds normally.

Test plan

  • Reproduce the bug on Linux desktop with Easynews-backed episodes (audio plays, video stuck loading)
  • Apply patch, rebuild, retest — video plays through cleanly
  • Confirm package:collection import is already present in the file (it is, used by randomBackDrop on the next line)

Personal Fork and others added 2 commits April 26, 2026 17:25
When primary is null and backDrop is an empty list (e.g. an Episode whose
Jellyfin item has no backdrop images at all), `backDrop?[0]` indexes an
empty list and throws RangeError. The whole semantic of a 'firstOrNull'
getter is to return null when the collection is empty.

Replaced with package:collection's firstOrNull extension (already
imported in this file), which has the correct empty-list behavior.

Symptom this fixes: on platforms where MediaControlsWrapper.play
synchronously evaluates `playBackItem.images?.firstOrNull` (any non-Web
desktop / mobile build), the unhandled RangeError escapes through the
playback init future chain and aborts video pipeline init while audio
(already buffered) keeps playing. Reported under DonutWare#57, DonutWare#159, DonutWare#215, DonutWare#429
and likely related.
PR/development builds were producing debug APKs, which on Android run
without AOT compilation and ship with the DEBUG ribbon. Switch dev
builds to --release and let the gradle config fall back to the debug
keystore when key.properties is absent, so release-mode APKs build
without requiring prod signing secrets on forks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@PartyDonut
Copy link
Copy Markdown
Collaborator

Already fixed in #969.

@PartyDonut PartyDonut closed this Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants