[GH-ISSUE #176] AttributeError: 'NoneType' object has no attribute 'split' when calling util.prompt_for_user_token with a cached token of None scope #89

Closed
opened 2026-02-27 23:20:46 +03:00 by kerem · 23 comments
Owner

Originally created by @jj1118 on GitHub (Mar 29, 2017).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/176

Minimal example:

from spotipy.util import prompt_for_user_token
token = prompt_for_user_token(some_username, None, some_client_id, some_client_secret, some_redirect_uri)
# Now a cached token with None scope exists
token2 = prompt_for_user_token(some_username, None, some_client_id, some_client_secret, some_redirect_uri)
# AttributeError occurs

(Note scope=None is default for util.prompt_for_user_token())
Traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token
    token_info = sp_oauth.get_cached_token()
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token
    if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 156, in _is_scope_subset
    needle_scope = set(needle_scope.split())
AttributeError: 'NoneType' object has no attribute 'split'

This breaks the program when being runned a second time with existence of cache on disk, which previously (back before last December I believe) did not happen.

Originally created by @jj1118 on GitHub (Mar 29, 2017). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/176 Minimal example: ```Python from spotipy.util import prompt_for_user_token token = prompt_for_user_token(some_username, None, some_client_id, some_client_secret, some_redirect_uri) # Now a cached token with None scope exists token2 = prompt_for_user_token(some_username, None, some_client_id, some_client_secret, some_redirect_uri) # AttributeError occurs ``` (Note `scope=None` is default for `util.prompt_for_user_token()`) Traceback: ```Python Traceback (most recent call last): File "<stdin>", line 1, in <module> File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token token_info = sp_oauth.get_cached_token() File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']): File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 156, in _is_scope_subset needle_scope = set(needle_scope.split()) AttributeError: 'NoneType' object has no attribute 'split' ``` This breaks the program when being runned a second time with existence of cache on disk, which previously (back before last December I believe) did not happen.
kerem 2026-02-27 23:20:46 +03:00
Author
Owner

@sachag678 commented on GitHub (Apr 2, 2017):

I am having the same issue. It worked the first time but it fails the second time,

<!-- gh-comment-id:291012582 --> @sachag678 commented on GitHub (Apr 2, 2017): I am having the same issue. It worked the first time but it fails the second time,
Author
Owner

@anirudh3 commented on GitHub (Apr 11, 2017):

Got the same issue!

I think this might be a bug. If we don't pass a valid scope the first time a user token is generated and authorized successfully, then from next time onwards, the get_cached_token() function is susceptible to returning 'None' (line 135 in oauth2.py), even if you set the scope this time. Maybe, this is it, though I need to download the library, make changes and try it out. I had used installed version till now.

<!-- gh-comment-id:293196533 --> @anirudh3 commented on GitHub (Apr 11, 2017): Got the same issue! I think this might be a bug. If we don't pass a valid scope the first time a user token is generated and authorized successfully, then from next time onwards, the get_cached_token() function is susceptible to returning 'None' (line 135 in oauth2.py), even if you set the scope this time. Maybe, this is it, though I need to download the library, make changes and try it out. I had used installed version till now.
Author
Owner

@josduj commented on GitHub (Apr 24, 2017):

Use the github version, it should be fixed.

<!-- gh-comment-id:296559687 --> @josduj commented on GitHub (Apr 24, 2017): Use the github version, it should be fixed.
Author
Owner

@jj1118 commented on GitHub (Apr 24, 2017):

@josduj Using Github version, now the error becomes:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token
    token_info = sp_oauth.get_cached_token()
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token
    if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 161, in _is_scope_subset
    return needle_scope <= haystack_scope
TypeError: unorderable types: NoneType() <= NoneType()
<!-- gh-comment-id:296563244 --> @jj1118 commented on GitHub (Apr 24, 2017): @josduj Using Github version, now the error becomes: ```Python Traceback (most recent call last): File "<stdin>", line 1, in <module> File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token token_info = sp_oauth.get_cached_token() File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']): File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 161, in _is_scope_subset return needle_scope <= haystack_scope TypeError: unorderable types: NoneType() <= NoneType() ```
Author
Owner

@sachag678 commented on GitHub (Apr 24, 2017):

It started working for me.

I just deleted the original user token and now it works every time I use it

On Mon, Apr 24, 2017 at 3:52 AM, Jason Li notifications@github.com wrote:

@josduj https://github.com/josduj Using Github version, now the error
becomes:

Traceback (most recent call last):
File "", line 1, in
File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token
token_info = sp_oauth.get_cached_token()
File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token
if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 161, in _is_scope_subset
return needle_scope <= haystack_scopeTypeError: unorderable types: NoneType() <= NoneType()


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/plamere/spotipy/issues/176#issuecomment-296563244,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ASwCUVk9kg90n-lSXb-zb05VEG4A8uUsks5rzFS7gaJpZM4Mscjq
.

<!-- gh-comment-id:296714029 --> @sachag678 commented on GitHub (Apr 24, 2017): It started working for me. I just deleted the original user token and now it works every time I use it On Mon, Apr 24, 2017 at 3:52 AM, Jason Li <notifications@github.com> wrote: > @josduj <https://github.com/josduj> Using Github version, now the error > becomes: > > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token > token_info = sp_oauth.get_cached_token() > File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token > if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']): > File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 161, in _is_scope_subset > return needle_scope <= haystack_scopeTypeError: unorderable types: NoneType() <= NoneType() > > — > You are receiving this because you commented. > Reply to this email directly, view it on GitHub > <https://github.com/plamere/spotipy/issues/176#issuecomment-296563244>, > or mute the thread > <https://github.com/notifications/unsubscribe-auth/ASwCUVk9kg90n-lSXb-zb05VEG4A8uUsks5rzFS7gaJpZM4Mscjq> > . >
Author
Owner

@ghost commented on GitHub (May 3, 2017):

This issue is present on the "Shows the contents of every playlist owned by a user" example on the website documentation as well. fixed by setting scope='user-library-read' before prompting user token.

<!-- gh-comment-id:298807800 --> @ghost commented on GitHub (May 3, 2017): This issue is present on the "Shows the contents of every playlist owned by a user" example on the website documentation as well. fixed by setting scope='user-library-read' before prompting user token.
Author
Owner

@ulgens commented on GitHub (Jun 11, 2017):

Simple workaround:

import os
from json.decoder import JSONDecodeError

scope = <whatever_youwant>
try:
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
except (AttributeError, JSONDecodeError):
    os.remove(f".cache-{username}")
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
<!-- gh-comment-id:307632735 --> @ulgens commented on GitHub (Jun 11, 2017): Simple workaround: ``` import os from json.decoder import JSONDecodeError scope = <whatever_youwant> try: token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri) except (AttributeError, JSONDecodeError): os.remove(f".cache-{username}") token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri) ```
Author
Owner

@diogofm commented on GitHub (Jun 17, 2017):

Thanks @ulgens , your solution worked fine for me.

<!-- gh-comment-id:309230966 --> @diogofm commented on GitHub (Jun 17, 2017): Thanks @ulgens , your solution worked fine for me.
Author
Owner

@netik commented on GitHub (Jun 28, 2017):

Adding the following to _is_scope_subset in oauth2.py fixes this issue. When I initially created my oauth token I did it on a create_playlist call. It seems that this creates a token with a scope of None and that breaks parsing. This is working for me but may be an incomplete fix.

     def _is_scope_subset(self, needle_scope, haystack_scope):
       if needle_scope == None and haystack_scope == None:
             return True
 
<!-- gh-comment-id:311758131 --> @netik commented on GitHub (Jun 28, 2017): Adding the following to _is_scope_subset in oauth2.py fixes this issue. When I initially created my oauth token I did it on a create_playlist call. It seems that this creates a token with a scope of None and that breaks parsing. This is working for me but may be an incomplete fix. ``` def _is_scope_subset(self, needle_scope, haystack_scope): if needle_scope == None and haystack_scope == None: return True ```
Author
Owner

@gwynnebaer commented on GitHub (Jul 7, 2017):

I can confirm that @Perolus commit works for me.

<!-- gh-comment-id:313816869 --> @gwynnebaer commented on GitHub (Jul 7, 2017): I can confirm that @Perolus commit works for me.
Author
Owner

@patalanov commented on GitHub (Aug 2, 2017):

how can one delete the original user token with None scope?

<!-- gh-comment-id:319809334 --> @patalanov commented on GitHub (Aug 2, 2017): how can one delete the original user token with None scope?
Author
Owner

@patalanov commented on GitHub (Aug 2, 2017):

import os
from json.decoder import JSONDecodeError

scope = <whatever_youwant>
try:
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
except (AttributeError, JSONDecodeError):
    os.remove(f".cache-{username}")
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)

this does not work for me. why do I get syntax error in

os.remove(f".cache-{username}")

where is this file located?

<!-- gh-comment-id:319813180 --> @patalanov commented on GitHub (Aug 2, 2017): ``` import os from json.decoder import JSONDecodeError scope = <whatever_youwant> try: token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri) except (AttributeError, JSONDecodeError): os.remove(f".cache-{username}") token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri) ``` this does not work for me. why do I get syntax error in ``` os.remove(f".cache-{username}") ``` where is this file located?
Author
Owner

@ulgens commented on GitHub (Aug 3, 2017):

@patalanov

os.remove(f".cache-{username}")

f strings are only supporterd after python 3.6. If you're using lower version, you should use .format() method. File is located under same folder with the code itself.

<!-- gh-comment-id:319885156 --> @ulgens commented on GitHub (Aug 3, 2017): @patalanov > os.remove(f".cache-{username}") f strings are only supporterd after python 3.6. If you're using lower version, you should use `.format()` method. File is located under same folder with the code itself.
Author
Owner

@ivancete commented on GitHub (Mar 19, 2018):

Thanks @ulgens it worked very fine.

<!-- gh-comment-id:374310687 --> @ivancete commented on GitHub (Mar 19, 2018): Thanks @ulgens it worked very fine.
Author
Owner

@jfaul commented on GitHub (Apr 8, 2018):

Hey @ivancete, I'm having the same problem you had, what was the code that you inserted using the .format()? Thanks!

<!-- gh-comment-id:379591438 --> @jfaul commented on GitHub (Apr 8, 2018): Hey @ivancete, I'm having the same problem you had, what was the code that you inserted using the .format()? Thanks!
Author
Owner

@wyattshapiro commented on GitHub (Sep 7, 2018):

@jfaul The line of code using .format would be os.remove(".cache-{}".format(username))

<!-- gh-comment-id:419593224 --> @wyattshapiro commented on GitHub (Sep 7, 2018): @jfaul The line of code using .format would be `os.remove(".cache-{}".format(username))`
Author
Owner

@roydemirjian commented on GitHub (Oct 16, 2018):

@ulgens worked perfectly thank you

<!-- gh-comment-id:430361943 --> @roydemirjian commented on GitHub (Oct 16, 2018): @ulgens worked perfectly thank you
Author
Owner

@amirkatzster commented on GitHub (Feb 10, 2019):

A hidden file is created called .cache-{username} can be also deleted manually

<!-- gh-comment-id:462112122 --> @amirkatzster commented on GitHub (Feb 10, 2019): A hidden file is created called .cache-{username} can be also deleted manually
Author
Owner

@OliverPearmain commented on GitHub (Mar 17, 2019):

I was getting this problem because I wasn't passing the returned token when instanciating the spotipy.Spotify instance.

I was doing this....

util.prompt_for_user_token("User")
spotify = spotipy.Spotify()

When I should have been doing this...

token = util.prompt_for_user_token("User")
spotify = spotipy.Spotify(auth=token)
<!-- gh-comment-id:473708503 --> @OliverPearmain commented on GitHub (Mar 17, 2019): I was getting this problem because I wasn't passing the returned `token` when instanciating the `spotipy.Spotify` instance. I was doing this.... ``` util.prompt_for_user_token("User") spotify = spotipy.Spotify() ``` When I should have been doing this... ``` token = util.prompt_for_user_token("User") spotify = spotipy.Spotify(auth=token) ```
Author
Owner

@conorhennessy commented on GitHub (Mar 28, 2019):

Many thanks to @ulgens and @wyattshapiro whos fixes outlined above saved the day!

<!-- gh-comment-id:477434497 --> @conorhennessy commented on GitHub (Mar 28, 2019): Many thanks to @ulgens and @wyattshapiro whos fixes outlined above saved the day!
Author
Owner

@mdreynes commented on GitHub (Aug 26, 2019):

I changed the function at line 155 with this

def _is_scope_subset(self, needle_scope, haystack_scope):
    if needle_scope:
        needle_scope = set(needle_scope.split())
    else:
        needle_scope = ""
    if haystack_scope:
        haystack_scope = set(haystack_scope.split())
    else:
        haystack_scope = ""
    return needle_scope <= haystack_scope

and it works.

Maybe I've done something wrong (I have a lot to learn in Python) but for now is working

<!-- gh-comment-id:524982429 --> @mdreynes commented on GitHub (Aug 26, 2019): I changed the function at line 155 with this def _is_scope_subset(self, needle_scope, haystack_scope): if needle_scope: needle_scope = set(needle_scope.split()) else: needle_scope = "" if haystack_scope: haystack_scope = set(haystack_scope.split()) else: haystack_scope = "" return needle_scope <= haystack_scope and it works. Maybe I've done something wrong (I have a lot to learn in Python) but for now is working
Author
Owner

@ezekini commented on GitHub (Feb 10, 2020):

Hello. I was using the library without any trouble, but suddenly I got the same error. I am authenticating using:

import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
from config import SPOT_CLIENT_ID, SPOT_CLIENT_SECRET
client_credentials_manager = SpotifyClientCredentials(client_id=SPOT_CLIENT_ID,
                                                      client_secret=SPOT_CLIENT_SECRET)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

I tried deleting the hidden file without luck. I am using the latest version of the library. Any ideas on what may be happening?

<!-- gh-comment-id:584400708 --> @ezekini commented on GitHub (Feb 10, 2020): Hello. I was using the library without any trouble, but suddenly I got the same error. I am authenticating using: ``` import spotipy from spotipy.oauth2 import SpotifyClientCredentials from config import SPOT_CLIENT_ID, SPOT_CLIENT_SECRET client_credentials_manager = SpotifyClientCredentials(client_id=SPOT_CLIENT_ID, client_secret=SPOT_CLIENT_SECRET) sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) ``` I tried deleting the hidden file without luck. I am using the latest version of the library. Any ideas on what may be happening?
Author
Owner

@stephanebruckert commented on GitHub (Jun 26, 2021):

Closing as wontfix as util.prompt_for_user_token() will be removed in v3

<!-- gh-comment-id:869059612 --> @stephanebruckert commented on GitHub (Jun 26, 2021): Closing as wontfix as `util.prompt_for_user_token()` will be removed in v3
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#89
No description provided.