Fix playlist download issues and improve logging experience#944
Open
geekinsanemx wants to merge 1 commit intonathom:devfrom
Open
Fix playlist download issues and improve logging experience#944geekinsanemx wants to merge 1 commit intonathom:devfrom
geekinsanemx wants to merge 1 commit intonathom:devfrom
Conversation
This commit fixes two IndexError crashes that prevented playlist downloads
and significantly improves the user experience by reducing log spam while
providing more informative error messages.
## Critical Bug Fixes
### 1. Fix crash when Deezer API returns empty tracks list
**Issue:** When downloading playlists, some tracks return album metadata with
an empty tracks list (`{"tracks": []}`), causing IndexError at album.py:165
when trying to access `resp["tracks"][-1]["disk_number"]`.
**Error:** `IndexError: list index out of range`
**Root Cause:** Code assumed tracks list always contains at least one track.
This happens with geo-restricted or removed albums that exist in Deezer's
database but have no accessible tracks.
**Fix:** Check if tracks list is empty before accessing the last element.
Default to `disctotal = 1` when list is empty (streamrip/metadata/album.py).
**Impact:** Playlist downloads now continue instead of crashing when
encountering unavailable albums.
### 2. Fix crash when requested quality exceeds source maximum
**Issue:** Requesting quality 3 or 4 on Deezer (which only supports 0-2)
caused IndexError at deezer.py:166 when accessing `size_map[quality]`.
**Error:** `IndexError: list index out of range`
**Root Cause:** User requests `--quality 3` (Hi-Res), but Deezer's quality_map
only has 3 elements (indices 0, 1, 2). Code tried to access index 3 which
doesn't exist.
**Fix:** Implemented smart quality clamping in base Client class. Each source
declares its max_quality (Deezer=2, Tidal=3, Qobuz=4, SoundCloud=3), and
requests are automatically clamped to the maximum supported quality.
**New Behavior:**
- Warns ONCE per session: "Requested quality 3 exceeds Deezer maximum (quality 2).
Using highest available quality (2) for all tracks."
- Automatically uses highest available quality for all subsequent tracks
- No more repeated warnings or crashes
**Impact:** Users can use `--quality 3` or `--quality 4` globally, and each
source will automatically use its maximum quality without crashes.
### 3. Fix version check showing false update notifications
**Issue:** Running development version (2.2.0) showed "new version 2.1.0
available" because code only checked if versions were different, not if
PyPI version was actually newer.
**Root Cause:** Version comparison used `!=` instead of `>`, so any difference
triggered the update message.
**Fix:** Changed to numeric version comparison using tuple comparison
(e.g., (2,2,0) > (2,1,0)).
**New Behavior:**
- Shows update message ONLY when PyPI version is numerically greater than
running version
- Running 2.2.0 with PyPI at 2.1.0 = No message
- Running 2.1.0 with PyPI at 2.2.0 = Shows message
## User Experience Improvements
### 4. Eliminate connection pool warning spam
**Issue:** Logs flooded with "Connection pool is full, discarding connection"
warnings every few seconds during playlist downloads.
**Root Cause:** urllib3 (used by deezer-py) has default pool size of 10.
Concurrent metadata fetches for 20+ tracks exhaust the pool.
**Fix:** Suppress urllib3.connectionpool logger warnings. These are performance
warnings, not failures - downloads work perfectly, just with new connections
instead of reused ones.
**Impact:** Clean logs without harmless warnings. Downloads unaffected.
### 5. Reduce quality fallback logging to DEBUG level
**Issue:** Logs spammed with "The requested quality 2 is not available.
Falling back to quality 1" for every track that lacks the requested quality.
**Fix:** Consolidated to single DEBUG-level message per track. Only logs when
fallback actually occurs, not for every quality level checked.
**Impact:** Significantly cleaner output. Enable debug logging if you want
to see which tracks fell back to lower quality.
### 6. Show track names in error messages
**Issue:** Error messages only showed track IDs, requiring users to manually
look up which songs failed: "Error fetching download info for track 964342"
**Fix:** Extract and display track title and artist from API response before
errors occur. Handle different API response formats (dict vs list for artist).
**New Error Format:**
- Before: `Error fetching download info for track 964342: Track not available...`
- After: `Error fetching download info for "Bohemian Rhapsody" by Queen: Track not available...`
**Impact:** Users instantly know which songs failed without looking up IDs.
### 7. Improve error messages for unavailable tracks
**Issue:** Generic "Missing download info. Skipping." didn't explain why.
**Fix:** More descriptive message: "Track not available for download (no file
sizes returned by API). Likely removed, geo-restricted, or licensing issue."
**Impact:** Users understand why tracks fail instead of wondering if it's a bug.
## Implementation Details
**New Base Class Method:** `Client.clamp_quality(requested_quality)`
- Implemented in base Client class (streamrip/client/client.py)
- Each source declares max_quality as class attribute
- Warns once per session if clamping occurs
- All clients (Deezer, Tidal, Qobuz, SoundCloud) now inherit this behavior
**Modified Files:**
- streamrip/client/client.py: Add clamp_quality() base method
- streamrip/client/deezer.py: Use clamp_quality(), suppress warnings
- streamrip/client/qobuz.py: Add super().__init__() call
- streamrip/client/tidal.py: Add super().__init__() call
- streamrip/client/soundcloud.py: Add super().__init__() call, set max_quality
- streamrip/client/downloadable.py: Improve error message for missing download info
- streamrip/media/playlist.py: Extract track names for error messages
- streamrip/metadata/album.py: Handle empty tracks list safely
- streamrip/rip/cli.py: Fix version comparison logic
## Testing
Tested with:
- Deezer playlists containing geo-restricted tracks
- Quality 3 and 4 requests on all sources
- Empty tracks list responses
- Version check with dev version vs PyPI version
All previously crashing scenarios now work correctly with informative messages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR addresses some IndexError bugs that were stopping playlist downloads and makes the download experience much cleaner by reducing log spam and providing more helpful error messages.
Bug Fixes
1. Handle empty tracks list from Deezer API
What was happening: Some tracks in playlists (especially geo-restricted ones) return album metadata with an empty tracks list, which caused an
IndexErrorwhen trying to access the last track's disc number.Why it happened: The code assumed there's always at least one track in the list. This can happen with albums that exist in Deezer's database but don't have accessible tracks in your region.
What changed: Now we check if the tracks list is empty before accessing it, and default to
disctotal = 1when needed.Result: Playlist downloads keep going even when they encounter unavailable albums, instead of stopping completely.
2. Smart quality handling across all sources
What was happening: Using
--quality 3or--quality 4on Deezer (which only supports up to quality 2) caused an IndexError.Why it happened: Deezer's quality map only has 3 quality levels (0, 1, 2), so requesting index 3 was out of bounds.
What changed: Added automatic quality clamping in the base Client class. Each source now declares its maximum quality:
Result: You can now use
--quality 3or--quality 4everywhere, and each source automatically uses its highest available quality. Shows a friendly one-time warning like: "Requested quality 3 exceeds Deezer maximum (quality 2). Using highest available quality (2) for all tracks."3. Better version update detection
What was happening: Development versions showed "new version available" messages even when the PyPI version was older.
Why it happened: Version check used
!=instead of>, so any difference triggered the notification.What changed: Now uses proper numeric comparison (e.g., 2.2.0 > 2.1.0).
Result: Update notifications only show when there's actually a newer version on PyPI.
User Experience Improvements
4. Cleaner logs - no more connection pool warnings
What was happening: Logs were flooded with "Connection pool is full" warnings during playlist downloads.
What changed: These urllib3 warnings are now suppressed since they're just performance warnings - downloads work perfectly fine.
Result: Much cleaner log output without harmless warnings.
5. Quality fallback messages are now quieter
What was happening: Console showed "Quality X not available, falling back..." for every single track.
What changed: These messages are now at DEBUG level, so they don't clutter the output.
Result: Cleaner console output. You can still enable debug logging if you want to see the quality fallback details.
6. Error messages now show actual song names
What was happening: Errors only showed track IDs like "Error for track 964342", so you had to look up which song that was.
What changed: Now extracts and shows the track title and artist from the API response.
Example:
Error fetching download info for track 964342Error fetching download info for "Bohemian Rhapsody" by QueenResult: You instantly know which songs had issues without needing to look up IDs.
7. More helpful error messages
What was happening: Generic messages like "Missing download info. Skipping." didn't explain why tracks failed.
What changed: More descriptive messages like "Track not available for download (no file sizes returned by API). Likely removed, geo-restricted, or licensing issue."
Result: You understand why tracks fail instead of wondering if it's a bug.
Technical Details
New feature:
Client.clamp_quality()base class methodFiles modified:
streamrip/client/client.py- Add clamp_quality() base methodstreamrip/client/deezer.py- Use clamp_quality(), suppress connection warningsstreamrip/client/qobuz.py- Add super().init() callstreamrip/client/tidal.py- Add super().init() callstreamrip/client/soundcloud.py- Add super().init() call, set max_qualitystreamrip/client/downloadable.py- Better error messagesstreamrip/media/playlist.py- Extract track names for errorsstreamrip/metadata/album.py- Handle empty tracks list safelystreamrip/rip/cli.py- Fix version comparison logicTesting
Tested with: