[GH-ISSUE #1156] Fails to query audio features for LOCAL track files that aren't available #681

Closed
opened 2026-02-28 00:00:48 +03:00 by kerem · 6 comments
Owner

Originally created by @tprebenda on GitHub (Aug 21, 2024).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/1156

Describe the bug

When a playlist contains LOCAL track files (uploaded to Spotify by a user), specifically ones that are greyed out in the Spotify app (no longer available?), Spotipy will retrieve them when querying a playlist, but it will then error out when trying to query audio features for those songs.

Error: TypeError: expected string or bytes-like object (presumably because local track files don't contain the expected values used by Spotipy internally?)

Your code

sp = spotipy.Spotify(auth=access_token)
tracks_response = sp.playlist_tracks(playlistId)
tracks = tracks_response["items"]
while tracks_response["next"]:
    tracks_response = sp.next(tracks_response)
    tracks.extend(tracks_response["items"])

track_ids = [track["track"]["id"] for track in tracks][:100]
# ERROR HERE:
audio_features = sp.audio_features(track_ids)

Expected behavior

Local files should be skipped completely (not retrieved when querying playlist tracks), or they should be skipped when querying audio features

Output

Traceback (most recent call last):
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 399, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 70, in __call__
    return await self.app(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\fastapi\applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\applications.py", line 123, in __call__
    await self.middleware_stack(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
    raise exc
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\sessions.py", line 85, in __call__
    await self.app(scope, receive, send_wrapper)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\cors.py", line 93, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\cors.py", line 148, in simple_response
    await self.app(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\exceptions.py", line 65, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
    raise exc
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    await app(scope, receive, sender)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 756, in __call__
    await self.middleware_stack(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 776, in app
    await route.handle(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 297, in handle
    await self.app(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 77, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
    raise exc
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    await app(scope, receive, sender)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 72, in app
    response = await func(request)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\fastapi\routing.py", line 278, in app
    raw_response = await run_endpoint_function(
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\fastapi\routing.py", line 191, in run_endpoint_function
    return await dependant.call(**values)
  File "D:\repos\spotify-mood-evaluator-api\main.py", line 169, in getPlaylistMood
    audio_features = sp.audio_features(track_ids)
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\spotipy\client.py", line 1752, in audio_features
    tlist = [self._get_id("track", t) for t in tracks]
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\spotipy\client.py", line 1752, in <listcomp>
    tlist = [self._get_id("track", t) for t in tracks]
  File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\spotipy\client.py", line 1985, in _get_id
    uri_match = re.search(Spotify._regex_spotify_uri, id)
  File "C:\Python310\lib\re.py", line 200, in search
    return _compile(pattern, flags).search(string)
TypeError: expected string or bytes-like object

Environment:

  • OS: Windows
  • Python version 3.10.6
  • spotipy version 2.24.0
  • your IDE (if using any): VSCode
Originally created by @tprebenda on GitHub (Aug 21, 2024). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/1156 **Describe the bug** When a playlist contains LOCAL track files (uploaded to Spotify by a user), specifically ones that are greyed out in the Spotify app (no longer available?), Spotipy will retrieve them when querying a playlist, but it will then error out when trying to query audio features for those songs. Error: `TypeError: expected string or bytes-like object` (presumably because local track files don't contain the expected values used by Spotipy internally?) **Your code** ``` sp = spotipy.Spotify(auth=access_token) tracks_response = sp.playlist_tracks(playlistId) tracks = tracks_response["items"] while tracks_response["next"]: tracks_response = sp.next(tracks_response) tracks.extend(tracks_response["items"]) track_ids = [track["track"]["id"] for track in tracks][:100] # ERROR HERE: audio_features = sp.audio_features(track_ids) ``` **Expected behavior** Local files should be skipped completely (not retrieved when querying playlist tracks), or they should be skipped when querying audio features **Output** ``` Traceback (most recent call last): File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 399, in run_asgi result = await app( # type: ignore[func-returns-value] File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 70, in __call__ return await self.app(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\fastapi\applications.py", line 1054, in __call__ await super().__call__(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\applications.py", line 123, in __call__ await self.middleware_stack(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\errors.py", line 186, in __call__ raise exc File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\errors.py", line 164, in __call__ await self.app(scope, receive, _send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\sessions.py", line 85, in __call__ await self.app(scope, receive, send_wrapper) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\cors.py", line 93, in __call__ await self.simple_response(scope, receive, send, request_headers=headers) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\cors.py", line 148, in simple_response await self.app(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\middleware\exceptions.py", line 65, in __call__ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app raise exc File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app await app(scope, receive, sender) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 756, in __call__ await self.middleware_stack(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 776, in app await route.handle(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 297, in handle await self.app(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 77, in app await wrap_app_handling_exceptions(app, request)(scope, receive, send) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app raise exc File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app await app(scope, receive, sender) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\starlette\routing.py", line 72, in app response = await func(request) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\fastapi\routing.py", line 278, in app raw_response = await run_endpoint_function( File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\fastapi\routing.py", line 191, in run_endpoint_function return await dependant.call(**values) File "D:\repos\spotify-mood-evaluator-api\main.py", line 169, in getPlaylistMood audio_features = sp.audio_features(track_ids) File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\spotipy\client.py", line 1752, in audio_features tlist = [self._get_id("track", t) for t in tracks] File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\spotipy\client.py", line 1752, in <listcomp> tlist = [self._get_id("track", t) for t in tracks] File "D:\repos\spotify-mood-evaluator-api\.venv\lib\site-packages\spotipy\client.py", line 1985, in _get_id uri_match = re.search(Spotify._regex_spotify_uri, id) File "C:\Python310\lib\re.py", line 200, in search return _compile(pattern, flags).search(string) TypeError: expected string or bytes-like object ``` **Environment:** - OS: Windows - Python version 3.10.6 - spotipy version 2.24.0 - your IDE (if using any): VSCode
kerem 2026-02-28 00:00:48 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@dieser-niko commented on GitHub (Aug 21, 2024):

I don't think that it should be skipped/ignored as this might confuse others even more. However, I'd say that the error is a bit too vague. I just wouldn't expect this kind of error message.

<!-- gh-comment-id:2302989624 --> @dieser-niko commented on GitHub (Aug 21, 2024): I don't think that it should be skipped/ignored as this might confuse others even more. However, I'd say that the error is a bit too vague. I just wouldn't expect this kind of error message.
Author
Owner

@tprebenda commented on GitHub (Aug 21, 2024):

Confuse others more? How so?

If we don't skip them, Spotipy will error out every time it tries to query for Audio Features for local tracks. Local tracks are common enough on Spotify that Spotipy should be able to handle it properly...

<!-- gh-comment-id:2303022512 --> @tprebenda commented on GitHub (Aug 21, 2024): Confuse others more? How so? If we don't skip them, Spotipy will error out every time it tries to query for Audio Features for local tracks. Local tracks are common enough on Spotify that Spotipy should be able to handle it properly...
Author
Owner

@dieser-niko commented on GitHub (Aug 21, 2024):

Confuse others more? How so?

If Spotipy ignored this, other people might come across it and suspect that it just doesn't work, rather than getting an error telling them what's wrong. In my opinion it's the programmer's responsibility to ensure that the track is not local.

Also I've debugged your code and it seems that the ID of a local track is None. A possible quick fix would be:

track_ids = [track["track"]["id"] for track in tracks if not track["is_local"]][:100]
<!-- gh-comment-id:2303233946 --> @dieser-niko commented on GitHub (Aug 21, 2024): > Confuse others more? How so? If Spotipy ignored this, other people might come across it and suspect that it just doesn't work, rather than getting an error telling them what's wrong. In my opinion it's the programmer's responsibility to ensure that the track is not local. Also I've debugged your code and it seems that the ID of a local track is None. A possible quick fix would be: ```python track_ids = [track["track"]["id"] for track in tracks if not track["is_local"]][:100] ```
Author
Owner

@tprebenda commented on GitHub (Aug 22, 2024):

Fair enough, then the error message should definitely be more clear about the source.

Also thanks, I already handled it :)

<!-- gh-comment-id:2303324092 --> @tprebenda commented on GitHub (Aug 22, 2024): Fair enough, then the error message should definitely be more clear about the source. Also thanks, I already handled it :)
Author
Owner

@dieser-niko commented on GitHub (Aug 22, 2024):

In this case the error message should be fine as one of the inputs was not an expected type.
I'm going to close the issue as it seems to be resolved.

<!-- gh-comment-id:2304427730 --> @dieser-niko commented on GitHub (Aug 22, 2024): In this case the error message should be fine as one of the inputs was not an expected type. I'm going to close the issue as it seems to be resolved.
Author
Owner

@tprebenda commented on GitHub (Aug 22, 2024):

I definitely think it'd be worth improving the error message from Spotipy for this particular type error, but understood.

<!-- gh-comment-id:2305106467 --> @tprebenda commented on GitHub (Aug 22, 2024): I definitely think it'd be worth improving the error message from Spotipy for this particular type error, but understood.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/spotipy#681
No description provided.