linsomniac / spotify_to_ytmusic

Copy playlists and liked music from Spotify to YTMusic
Creative Commons Zero v1.0 Universal
1.95k stars 119 forks source link

Copy all playlist fails: KeyError 'runs' #31

Open notSoWiseOldMan opened 8 months ago

notSoWiseOldMan commented 8 months ago

I think there is some missing error handling or the api response from spotify was updated.

root@05b4935821ac:/# s2yt_copy_all_playlists
Traceback (most recent call last):
  File "/usr/local/bin/s2yt_copy_all_playlists", line 8, in <module>
    sys.exit(copy_all_playlists())
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/cli.py", line 264, in copy_all_playlists
    backend.copy_all_playlists(
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/backend.py", line 441, in copy_all_playlists
    dst_pl_id = get_playlist_id_by_name(yt, pl_name)
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/backend.py", line 163, in get_playlist_id_by_name
    for pl in yt.get_library_playlists(limit=5000):
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/mixins/library.py", line 35, in get_library_playlists
    playlists = parse_content_list(results["items"][1:], parse_playlist)
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/parsers/browsing.py", line 48, in parse_content_list
    contents.append(parse_func(result[key]))
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/parsers/browsing.py", line 126, in parse_playlist
    "title": nav(data, TITLE_TEXT),
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/navigation.py", line 103, in nav
    raise err
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/navigation.py", line 97, in nav
    root = root[k]
KeyError: 'runs'
linsomniac commented 8 months ago

I've done some investigation into this and this looks like a bug in ytmusicapi and I'm not sure what the correct resolution there is. I've filed bug https://github.com/sigma67/ytmusicapi/issues/539 over there. I've also detected this error in s2ytmusic and displayed a message about it.

I'm afraid that until this bug gets fixed in ytmusicapi, you won't be able to use "copy_all_playlists", you'll need to manually copy the playlists by playlist ID (the bug is in the code that lists the playlists, and that's how I search for a playlist by name, without being able to search for playlist by name, my code will just end up creating new, possibly duplicate playlists every run.

linsomniac commented 8 months ago

I just tried adding a patch to ytmusicapi to print out debug information in the event of a traceback. Can you try a python -m pip install --upgrade spotify2ytmusic and run copy_all_playlists again, hopefully it'll give an error and hopefully we can debug the issue.

notSoWiseOldMan commented 8 months ago

Thanks, Here is the output after updating that package. I will trying importing the Running playlist individually and see if it also chokes on that.

Attempting to look up playlist 'Running' failed with KeyError: 'runs'
This is a bug in ytmusicapi that prevents 'copy_all_playlists' from working.
You will need to manually copy playlists using s2yt_list_playlists and s2yt_copy_playlist
until this bug gets resolved.  Try `pip install --upgrade ytmusicapi` just to verify
you have the latest version of that library.
============================================================
Traceback (most recent call last):
  File "/usr/local/bin/s2yt_copy_all_playlists", line 8, in <module>
    sys.exit(copy_all_playlists())
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/cli.py", line 281, in copy_all_playlists
    backend.copy_all_playlists(
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/backend.py", line 461, in copy_all_playlists
    dst_pl_id = get_playlist_id_by_name(yt, pl_name)
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/backend.py", line 166, in get_playlist_id_by_name
    playlists = yt.get_library_playlists(limit=5000)
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/mixins/library.py", line 35, in get_library_playlists
    playlists = parse_content_list(results["items"][1:], parse_playlist)
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/parsers/browsing.py", line 48, in parse_content_list
    contents.append(parse_func(result[key]))
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/parsers/browsing.py", line 126, in parse_playlist
    "title": nav(data, TITLE_TEXT),
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/navigation.py", line 103, in nav
    raise err
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/navigation.py", line 97, in nav
    root = root[k]
KeyError: 'runs'
notSoWiseOldMan commented 8 months ago

I get a similar error when trying to import individual playlists. I re-ran ytmusicapi oauth first to be sure my token hadn't expired.

root@05b4935821ac:/# s2yt_copy_playlist 4p5biyMolajLyTtnZNBl4S +Jazzy
============================================================
Attempting to look up playlist 'Jazzy' failed with KeyError: 'runs'
This is a bug in ytmusicapi that prevents 'copy_all_playlists' from working.
You will need to manually copy playlists using s2yt_list_playlists and s2yt_copy_playlist
until this bug gets resolved.  Try `pip install --upgrade ytmusicapi` just to verify
you have the latest version of that library.
============================================================
Traceback (most recent call last):
  File "/usr/local/bin/s2yt_copy_playlist", line 8, in <module>
    sys.exit(copy_playlist())
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/cli.py", line 239, in copy_playlist
    backend.copy_playlist(
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/backend.py", line 407, in copy_playlist
    ytmusic_playlist_id = get_playlist_id_by_name(yt, pl_name)
  File "/usr/local/lib/python3.10/site-packages/spotify2ytmusic/backend.py", line 166, in get_playlist_id_by_name
    playlists = yt.get_library_playlists(limit=5000)
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/mixins/library.py", line 35, in get_library_playlists
    playlists = parse_content_list(results["items"][1:], parse_playlist)
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/parsers/browsing.py", line 48, in parse_content_list
    contents.append(parse_func(result[key]))
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/parsers/browsing.py", line 126, in parse_playlist
    "title": nav(data, TITLE_TEXT),
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/navigation.py", line 103, in nav
    raise err
  File "/usr/local/lib/python3.10/site-packages/ytmusicapi/navigation.py", line 97, in nav
    root = root[k]
KeyError: 'runs'
notSoWiseOldMan commented 8 months ago

Ok, I had an empty playlist that matched my youtube username. After deleting that playlist on youtube mustic both the individual playlist import and import all playlist functions worked. So I think there just needs to be a check somewhere when looking at the YT music playlist to handle if the playlist is empty.

IDK where that empty playlist came from. 2 things I can think of.

  1. I was an old google play music user so it may have come from the transfer to YT music which I never used back then.
  2. I am currently on a trial youtube premium account... maybe something about that created this playlist?

Anyway it is working for me now and I got all my music. Thank you for making this tool! I'll be using it to help my friends switch over!

linsomniac commented 8 months ago

I tried creating an empty playlist named after my username, and ran copy_playlist to "+Jazzy" and to my new empty playlist named after my userid, and neither one ended up triggering this, so there must have been something related to that playlist that was beyond just an empty playlist named after your username...