sigma67 / ytmusicapi

Unofficial API for YouTube Music
https://ytmusicapi.readthedocs.io
MIT License
1.68k stars 191 forks source link

search: `list index out of range` for some search terms #429

Closed ageisen2000 closed 1 year ago

ageisen2000 commented 1 year ago

Here is the dump

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\Scripts\spotify_to_ytmusic.exe\__main__.py", line 7, in <module>
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\spotify_to_ytmusic\main.py", line 86, in main
    args.func(args)
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\spotify_to_ytmusic\controllers.py", line 79, in liked
    _create_ytmusic(args, playlist, ytmusic)
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\spotify_to_ytmusic\controllers.py", line 60, in _create_ytmusic
    videoIds = ytmusic.search_songs(playlist["tracks"])
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\spotify_to_ytmusic\ytmusic.py", line 32, in search_songs
    result = self.api.search(query)
             ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\ytmusicapi\mixins\search.py", line 218, in search
    parse_search_results(results, search_result_types, type, category))
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\ytmusicapi\parsers\search.py", line 142, in parse_search_results
    return [
           ^
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\ytmusicapi\parsers\search.py", line 143, in <listcomp>
    parse_search_result(result[MRLIR], search_result_types, resultType, category)
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\ytmusicapi\parsers\search.py", line 80, in parse_search_result
    search_result['name'] = get_item_text(data, 1, 2)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adamg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\ytmusicapi\parsers\_utils.py", line 30, in get_item_text
    return column['text']['runs'][run_index]['text']
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
IndexError: list index out of range
dabidlu commented 1 year ago

Just got the same error; although seems to be a transient error. Rerunning, I was able to successfully create the playllist.

sigma67 commented 1 year ago

Can you identify the specific song that is causing the issue? You can perhaps add a print statement in the source code before each search query. This would actually be an upstream issue with ytmusicapi.

ageisen2000 commented 1 year ago

As far as I could tell it was never any specific song. It failed at a different spot every time

sigma67 commented 1 year ago

What is your version of ytmusicapi? pip show ytmusicapi

kler commented 1 year ago

I can confirm that the error is present within ytmusicapi 1.2.0.

As visible in the stack trace this comes from get_item_text() in ytmusicapi\parsers\_utils.py

I tried the migration several times, and failed at different points, so it's not consistent for a certain song for instance. The error depends on the data returned from Youtube Music, making ytmusicapi crash.

Code analysis

Looking at the variable called column in get_item_text() in the debugger, it only has the 0:th index, while the calling function calls it with a hard coded index of 2: search_result['name'] = get_item_text(data, 1, 2) (link to code)

image

In case it would be acceptable to ignore the missing entry, there is a param called none_if_absent, however this is not passed from the caller function, meaning that the bug itself is actually in the ytmusicapi, and not in its utilization in spotify_to_ytmusicAFAICT.

I've tried setting none_if_absent=True in the caller function parse_search_result() line 80, and does indeed make it work, but I have no idea what side effects it has or if I'm breaking some intended behaviour.

I also had a similar error in parse_menu_playlists() (link to code) where it calls nav(), which fails in the item called menu. I tried setting none_if_absent=True here as well, and it made the playlist creation succeed.

...
YouTube tracks: 4550/4612
YouTube tracks: 4560/4612
YouTube tracks: 4570/4612
YouTube tracks: 4580/4612
YouTube tracks: 4590/4612
YouTube tracks: 4600/4612
YouTube tracks: 4610/4612
Success: created playlist 'Discover Weekly Archive' at
https://music.youtube.com/playlist?list=...

Side note: Only 4,517 songs where actually created, but there may be duplicates, I don't know...

sigma67 commented 1 year ago

So I'm trying with some pretty large playlists right now but failing to reproduce. It might be something specific to your accounts or a very rare bug where the name is missing on a profile result.

It would be very helpful if you could add the following debugging code to your local ytmusicapi installation and paste the output data here whenever you see the issue. Instead of this line

https://github.com/sigma67/ytmusicapi/blob/6660058a47dc31cefe1c3686067aeef0333c2590/ytmusicapi/parsers/search.py#L80

add

        search_result['name'] = get_item_text(data, 1, 2, True)
        if search_result['name'] == None:
            print(data)
            sys.exit()  # optional to stop when you find the issue
sigma67 commented 1 year ago

Managed to reproduce. I figure it's safe to ignore the value if absent since there are no other flexitems on this type of search result (yet).

kler commented 1 year ago

Great, thx!

I also made a run with the changes you proposed, and this is the result:

{
    'trackingParams': 'CBQQyfQCGAAiEwiMtueJ2PiAAxXnzU8IHYFND-E=',
    'thumbnail': {
        'musicThumbnailRenderer': {
            'thumbnail': {},
            'thumbnailCrop': 'MUSIC_THUMBNAIL_CROP_CIRCLE',
            'thumbnailScale': 'MUSIC_THUMBNAIL_SCALE_ASPECT_FILL',
            'trackingParams': 'CBUQhL8CIhMIjLbnidj4gAMV581PCB2BTQ_h'}
    },
    'flexColumns': [
        {
            'musicResponsiveListItemFlexColumnRenderer': {
                'text': {'runs': [{'text': 'Radio FM 432hz'}]},
                'displayPriority': 'MUSIC_RESPONSIVE_LIST_ITEM_COLUMN_DISPLAY_PRIORITY_HIGH'}
        },
        {
            'musicResponsiveListItemFlexColumnRenderer': {
                'text': {
                    'runs': [
                        {'text': 'Profile'}
                    ]
                },
                'displayPriority': 'MUSIC_RESPONSIVE_LIST_ITEM_COLUMN_DISPLAY_PRIORITY_HIGH'
            }
        }
        ],
        'flexColumnDisplayStyle': 'MUSIC_RESPONSIVE_LIST_ITEM_FLEX_COLUMN_DISPLAY_STYLE_TWO_LINE_STACK',
        'navigationEndpoint': {
            'clickTrackingParams': 'CBQQyfQCGAAiEwiMtueJ2PiAAxXnzU8IHYFND-E=',
            'browseEndpoint': {
                'browseId': 'UCf95fGmczd-0lzsCviETqKA',
                'browseEndpointContextSupportedConfigs': {
                    'browseEndpointContextMusicConfig': {
                        'pageType': 'MUSIC_PAGE_TYPE_UNKNOWN'
                    }
                }
            }
        },
        'itemHeight': 'MUSIC_RESPONSIVE_LIST_ITEM_HEIGHT_TALL'
}

There is unfortunately also a second problem in the nav() function in navigation.py - but didn't store the stack trace from when I had the error. Will possibly come back with that in another bug report if I hit it again.