From 2e77d6544baab021e275c0beadb0add18d460ea7 Mon Sep 17 00:00:00 2001 From: devgianlu Date: Sat, 18 Jul 2026 12:06:41 +0200 Subject: [PATCH] fix: don't strand the track list at pos -1 when unshuffle re-fetch fails ToggleShuffle's unshuffle branch clears the paged list (setting pos to -1) and then re-fetches the context in order to seek back to the current track. If that re-fetch hit a transient page error from Spotify (e.g. a 404 from radio-router while paging a station/autoplay context), the list was left stranded at pos -1. The next access via iterHere()/get() then panicked with "invalid paged list position: -1", crashing the daemon since the player event loop has no panic recovery. Snapshot the list before the destructive clear() and roll back to the previous valid state on failure, so the shuffle toggle simply does not take effect instead of corrupting the list. Fixes #324 Co-Authored-By: Claude Opus 4.8 --- tracks/tracks.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tracks/tracks.go b/tracks/tracks.go index a33d0fdb..f9008c19 100644 --- a/tracks/tracks.go +++ b/tracks/tracks.go @@ -338,9 +338,16 @@ func (tl *List) ToggleShuffle(ctx context.Context, shuffle bool) error { // remember current track currentTrack := tl.current() - // clear tracks and seek to the current track + // Clear tracks and re-fetch them in order, then seek to the current + // track. Snapshot the list first: a failed re-fetch (e.g. a transient + // error while paging the context) would otherwise leave the list + // stranded at pos -1, and the next access would panic. On failure we + // roll back to the previous (valid) state and report the error, so the + // shuffle toggle simply does not take effect. + savedList, savedPos := tl.tracks.list, tl.tracks.pos tl.tracks.clear() if err := tl.Seek(ctx, ContextTrackComparator(tl.ctx.Type(), currentTrack)); err != nil { + tl.tracks.list, tl.tracks.pos = savedList, savedPos return fmt.Errorf("failed seeking to current track: %w", err) }