Fix Tidal 404 handling: share links, missing lyrics, and the crashing handler - #1024
Open
sjbrownrigg wants to merge 4 commits into
Open
Fix Tidal 404 handling: share links, missing lyrics, and the crashing handler#1024sjbrownrigg wants to merge 4 commits into
sjbrownrigg wants to merge 4 commits into
Conversation
logger.warning("TIDAL: track not found", resp) passes an argument to a
message with no format placeholder, so logging raises
TypeError: not all arguments converted during string formatting
as soon as the record is actually formatted. A 404 from the API -- an
unavailable or region-restricted item, or a bad id -- therefore crashed
with a traceback from inside logging instead of reporting the
NonStreamableError on the next line.
Add the placeholder and log the URL, which is the useful part.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tidal's share sheet produces urls like
https://tidal.com/album/152697662/u
URL_REGEX takes the last path segment as the item id, which it has to do
because Qobuz album urls look like /<locale>/album/<slug>/<id>. So the
trailing "/u" was parsed as the id, streamrip requested album "u", and
the API returned 404.
Strip that suffix before matching. It is specific to tidal.com urls, so
Qobuz and Deezer paths are untouched.
Combined with the 404 handler in the previous commit, the failure was
particularly hard to diagnose: the id was silently wrong, and the 404 it
caused crashed inside logging rather than reporting itself.
Adds a regression test covering the /u, /u/ and /browse/.../u forms.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
get_metadata() fetches lyrics for tracks, and the lyrics endpoint 404s
for any track nobody has written lyrics for -- which is a lot of them.
_api_request turns a 404 into NonStreamableError, but the lyrics fetch
only caught TypeError, so that error escaped get_metadata().
PendingTrack.resolve() understandably treats a NonStreamableError from
get_metadata() as "this track cannot be streamed" and skips it. The
result was that a track was dropped from an album download for the sole
reason that it had no lyrics:
WARNING TIDAL: item not found (404): .../tracks/152697671/lyrics
ERROR Track 152697671 not available for stream on tidal
Catch NonStreamableError alongside TypeError. Lyrics are optional
metadata and must not decide whether audio gets downloaded.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Most tracks have no lyrics, so the lyrics endpoint 404s constantly. That
produced two warnings per track -- one from the 404 handler and one from
the lyrics handler -- for something entirely normal:
WARNING TIDAL: item not found (404): .../tracks/152697671/lyrics
WARNING Failed to get lyrics for 152697671: TIDAL: Track not found
"Not found" is the expected answer here, not a problem. Worse, the noise
makes a real failure indistinguishable from the routine case.
Add ItemNotFoundError, a subclass of NonStreamableError raised for 404 so
existing handlers are unaffected, and let callers tell "does not exist"
from "failed to fetch":
- The 404 in _api_request now logs at debug. Callers that care report
it themselves at the right level, so it was duplicated anyway.
- A 404 fetching lyrics logs at debug: nothing was expected.
- Any other lyrics failure still warns, because lyrics that should have
been there and could not be fetched is worth knowing about.
Verified against three tracks known to have no lyrics: no warning-level
output at all, and a simulated non-404 lyrics failure still warns while
leaving the track downloadable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
scratchmex
approved these changes
Aug 13, 2026
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.
The problem
Pasting a link straight from Tidal's share sheet crashes:
Two separate bugs stack up here, and together they make the failure very hard to diagnose — the traceback points at
logging, and says nothing about the URL.1. The
/usuffix is parsed as the item idTidal's share sheet appends
/u.URL_REGEXtakes the last path segment as the item id, which it has to do because Qobuz album urls look like/<locale>/album/<slug>/<id>. So the suffix wins:streamrip then requests album
u, which 404s.2. The 404 handler crashes instead of reporting
The message has no format placeholder but an argument is passed, so
msg % argsraisesTypeErroras soon as the record is formatted — before theNonStreamableErroron the next line is ever reached. Any 404 from the Tidal API surfaces as aloggingtraceback rather than the intended error. This has been present since b01382f (#623).3. A track with no lyrics is dropped entirely
get_metadata()fetches lyrics for tracks. The lyrics endpoint 404s for any track nobody has written lyrics for, and_api_requestturns that intoNonStreamableError— but the lyrics fetch only caughtTypeError, so the error escapedget_metadata().PendingTrack.resolve()reasonably treats aNonStreamableErrorfromget_metadata()as "this track cannot be streamed", so the track was skipped. A track was dropped from an album download purely because it had no lyrics:On a 12-track album this silently cost 4 tracks.
What this changes
Fix crash when Tidal returns 404— add the missing placeholder and logresp.url, which is the useful part. A 404 now reportsNonStreamableErroras intended.Fix Tidal share links ending in /u— strip the suffix fromtidal.comurls before matching. Scoped to tidal.com, so Qobuz's/<locale>/album/<slug>/<id>form and Deezer urls are untouched.Don't drop Tidal tracks that have no lyrics— catchNonStreamableErroralongsideTypeErroraround the lyrics fetch. Lyrics are optional metadata and must not decide whether audio gets downloaded. Verified against the four tracks above: all four now resolve.Testing
Added
test_tidal_share_url_with_u_suffix, covering/u,/u/and/browse/.../u. It fails ondev(3 subtest failures) and passes with the fix.Verified the existing forms still parse to the same ids:
tidal.com/browse/track/...,listen.tidal.com/track/...,qobuz.com/fr-fr/album/<slug>/<id>,qobuz.com/us-en/album/name/id123456,deezer.com/en/track/....pytest tests/gives 60 passed, 7 skipped, and 1 failure intest_meta.py::test_album_metadata_qobuz(a genre assertion) which also fails unmodified ondev, so it is unrelated to this change.