Skip to content

Tidal: spurious "Failed to get lyrics ... not all arguments converted during string formatting" for tracks without lyrics #983

Description

@oxfordbags

Summary

When downloading from Tidal, any track that Tidal has no lyrics for prints:

Failed to get lyrics for <id>: not all arguments converted during string formatting

The download itself succeeds — this is spurious noise — but it appears for every lyric-less track (instrumentals, classical, etc.).

Root cause

The Tidal lyrics endpoint returns 404 for tracks without lyrics. That hits this line in _api_request:

https://github.com/nathom/streamrip/blob/main/streamrip/client/tidal.py#L356

if resp.status == 404:
    logger.warning("TIDAL: track not found", resp)   # <-- bug
    raise NonStreamableError("TIDAL: Track not found")

resp is passed as a positional logging arg, but the message string has no % placeholder. streamrip logs through rich.logging.RichHandler, which (unlike the stdlib default handler) re-raises the resulting formatting error instead of swallowing it via handleError. So a TypeError: not all arguments converted during string formatting propagates out of _api_request.

In the track-metadata path that exception is then caught here:

https://github.com/nathom/streamrip/blob/main/streamrip/client/tidal.py#L113-L128

elif media_type == "track":
    try:
        resp = await self._api_request(
            f"tracks/{item_id!s}/lyrics", base="https://listen.tidal.com/v1"
        )
        ...
    except TypeError as e:
        logger.warning(f"Failed to get lyrics for {item_id}: {e}")

...producing the user-visible warning. (The except TypeError is itself a hint that the real intent was to treat a missing-lyrics 404 as non-fatal — but it's catching it via the formatting-bug side effect rather than the actual NonStreamableError.)

Reproduction

Confirmed with a valid token (streamrip 2.2.0, git main, Python 3.13, macOS):

  • GET https://listen.tidal.com/v1/tracks/62300893/lyrics (Adele – "Hello") → 200 with lyrics (feature works fine).
  • GET .../tracks/135612114/lyrics (Bach – Cello Suite No. 1 Prelude, instrumental) → 404 → triggers the warning above.

Minimal demonstration that RichHandler re-raises the formatting error (stdlib default handler does not):

import logging
from rich.logging import RichHandler
logging.basicConfig(level="WARNING", format="%(message)s", handlers=[RichHandler()])
logging.getLogger("streamrip").warning("TIDAL: track not found", object())
# -> TypeError: not all arguments converted during string formatting

Suggested fix

Two small changes:

  1. Fix the malformed log call at tidal.py:356, e.g.:
    logger.debug("TIDAL: resource not found at %s/%s", base, path)
  2. Treat a missing-lyrics 404 as non-fatal explicitly instead of relying on the formatting bug, e.g. broaden the lyrics handler:
    except (TypeError, NonStreamableError):
        item["lyrics"] = ""

Happy to open a PR if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions