[GH-ISSUE #605] Spotify OAuth error : Couldn't read cache, Couldn't refresh token and Illegal URI #362

Closed
opened 2026-02-27 23:22:13 +03:00 by kerem · 9 comments
Owner

Originally created by @nahar-senior on GitHub (Nov 8, 2020).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/605

I have a couple of things that are going wrong, and I have spent a considerable amount of time to fix it. I was first able to run the code below, Initially I did not pass the cache path as a parameter to the auth_manager. The code worked for an hour (since the token expires every hour), I then started running into errors regarding token refresh.

I then added the cache path as an added parameter and am getting two errors:

  1. Couldn't read cache at <cache_path>
  2. Illegal URI .

I have already checked the Redirect URI on my spotify developer dashboard and it matches what I have passed to the script.

Could I get a way to fix this as well as refresh the token if it's expired?

code

import configparser
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import json
import os
import csv



class UserData():

    def __init__(self, config_path):
        config = configparser.ConfigParser()
        config.read(config_path)

        self.CLIENT_ID = config['AUTH']['cid']
        self.CLIENT_SECRET = config['AUTH']['secret']
        self.REDIRECT_URI = config['AUTH']['redirect_uri']
        self.USERNAME = config['AUTH']['username']
        self.CACHE = config['AUTH']['cache']
        self.HOME_DIR = config['PATH']['home_dir']
        self.top_artists = {}
        self.top_tracks = {}


    def get_top_artist(self, limit=None, time_range=None, offset=0):
        sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=self.CLIENT_ID,
                                                client_secret=self.CLIENT_SECRET,
                                                redirect_uri=self.REDIRECT_URI,
                                                scope="user-top-read", 
                                                username=self.USERNAME, 
                                                cache_path=self.CACHE))

        
        self.top_artists = sp.current_user_top_artists(limit=limit, offset=offset, time_range=time_range)

        with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.csv', 'w' ,newline='') as csvfile:

            writer = csv.writer(csvfile, delimiter = ',', quoting = csv.QUOTE_MINIMAL)
            writer.writerow(['sno', 'id', 'name', 'popularity', 'genre', 'uri', 'image_ref', 'follower_count'])

            for idx, item in enumerate(self.top_artists['items']):
                sno = idx
                id = item['id']
                name = item['name']
                popularity = item['popularity']
                genre = item['genres']
                uri = item['uri']
                image_ref = item['images'][2]['url']
                follower_count = item['followers']['total']

                writer.writerow([sno, id, name, popularity, genre, uri, image_ref, follower_count])

        with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.json', 'w') as myfile:
            print(myfile)
            json.dump(self.top_artists, myfile, indent=4, sort_keys=True)

        return self.top_artists

data = UserData(config_path='/Users/siddharthnahar/Dev/py_spotify/config.ini')
data.get_top_artist(limit=1)

Output

siddharthnahar@Siddharths-MBP py_spotify % /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data.py
Couldn't read cache at: .cache-'21ranjgq5en4j53pcqfcedopi'
Enter the URL you were redirected to: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data.py
Traceback (most recent call last):
  File "/Users/siddharthnahar/Dev/py_spotify/get_data.py", line 74, in <module>
    data = UserData(config_path='/Users/siddharthnahar/Dev/py_spotify/config.ini')
  File "/Users/siddharthnahar/Dev/py_spotify/get_data.py", line 33, in get_top_artist
    
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 1272, in current_user_top_artists
    return self._get(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 291, in _get
    return self._internal_call("GET", url, payload, kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 221, in _internal_call
    headers = self._auth_headers()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 212, in _auth_headers
    token = self.auth_manager.get_access_token(as_dict=False)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/oauth2.py", line 504, in get_access_token
    raise SpotifyOauthError(
spotipy.oauth2.SpotifyOauthError: error: invalid_request, error_description: code must be supplied
siddharthnahar@Siddharths-MBP py_spotify % /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data.py
Couldn't read cache at: '.cache-21ranjgq5en4j53pcqfcedopi'
Enter the URL you were redirected to: 

Environment:

  • OS: Mac
  • Python version 3.9
Originally created by @nahar-senior on GitHub (Nov 8, 2020). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/605 I have a couple of things that are going wrong, and I have spent a considerable amount of time to fix it. I was first able to run the code below, Initially I did not pass the cache path as a parameter to the auth_manager. The code worked for an hour (since the token expires every hour), I then started running into errors regarding token refresh. I then added the cache path as an added parameter and am getting two errors: 1. Couldn't read cache at <cache_path> 2. Illegal URI <Enter the URL you were redirected to>. I have already checked the Redirect URI on my spotify developer dashboard and it matches what I have passed to the script. Could I get a way to fix this as well as refresh the token if it's expired? **code** ```python import configparser import spotipy from spotipy.oauth2 import SpotifyOAuth import json import os import csv class UserData(): def __init__(self, config_path): config = configparser.ConfigParser() config.read(config_path) self.CLIENT_ID = config['AUTH']['cid'] self.CLIENT_SECRET = config['AUTH']['secret'] self.REDIRECT_URI = config['AUTH']['redirect_uri'] self.USERNAME = config['AUTH']['username'] self.CACHE = config['AUTH']['cache'] self.HOME_DIR = config['PATH']['home_dir'] self.top_artists = {} self.top_tracks = {} def get_top_artist(self, limit=None, time_range=None, offset=0): sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, redirect_uri=self.REDIRECT_URI, scope="user-top-read", username=self.USERNAME, cache_path=self.CACHE)) self.top_artists = sp.current_user_top_artists(limit=limit, offset=offset, time_range=time_range) with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.csv', 'w' ,newline='') as csvfile: writer = csv.writer(csvfile, delimiter = ',', quoting = csv.QUOTE_MINIMAL) writer.writerow(['sno', 'id', 'name', 'popularity', 'genre', 'uri', 'image_ref', 'follower_count']) for idx, item in enumerate(self.top_artists['items']): sno = idx id = item['id'] name = item['name'] popularity = item['popularity'] genre = item['genres'] uri = item['uri'] image_ref = item['images'][2]['url'] follower_count = item['followers']['total'] writer.writerow([sno, id, name, popularity, genre, uri, image_ref, follower_count]) with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.json', 'w') as myfile: print(myfile) json.dump(self.top_artists, myfile, indent=4, sort_keys=True) return self.top_artists data = UserData(config_path='/Users/siddharthnahar/Dev/py_spotify/config.ini') data.get_top_artist(limit=1) ``` **Output** ``` siddharthnahar@Siddharths-MBP py_spotify % /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data.py Couldn't read cache at: .cache-'21ranjgq5en4j53pcqfcedopi' Enter the URL you were redirected to: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data.py Traceback (most recent call last): File "/Users/siddharthnahar/Dev/py_spotify/get_data.py", line 74, in <module> data = UserData(config_path='/Users/siddharthnahar/Dev/py_spotify/config.ini') File "/Users/siddharthnahar/Dev/py_spotify/get_data.py", line 33, in get_top_artist File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 1272, in current_user_top_artists return self._get( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 291, in _get return self._internal_call("GET", url, payload, kwargs) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 221, in _internal_call headers = self._auth_headers() File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/client.py", line 212, in _auth_headers token = self.auth_manager.get_access_token(as_dict=False) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/spotipy/oauth2.py", line 504, in get_access_token raise SpotifyOauthError( spotipy.oauth2.SpotifyOauthError: error: invalid_request, error_description: code must be supplied siddharthnahar@Siddharths-MBP py_spotify % /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data.py Couldn't read cache at: '.cache-21ranjgq5en4j53pcqfcedopi' Enter the URL you were redirected to: ``` **Environment:** - OS: Mac - Python version 3.9
kerem 2026-02-27 23:22:13 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@Peter-Schorn commented on GitHub (Nov 8, 2020):

Do not create a new instance of Spotify each time you call get_top_artist. You should create it in the initializer for UserData instead. Your script should only ever create a single instance of Spotify for each Spotify user. The reason your are getting a "Couldn't read cache at <cache_path>" error may simply be because the first time you create an instance of Spotify the cache file does not exist. Have you checked whether it does exist? If the file does not exist and you are running the script for the first time (or the first time since you changed the cache path), then you can safely ignore this error.

In order to provide more help I will need to see what your config file looks like. If you post it here, make sure to redact sensitive information, such as your client id and client secret.

<!-- gh-comment-id:723649108 --> @Peter-Schorn commented on GitHub (Nov 8, 2020): Do not create a new instance of `Spotify` each time you call `get_top_artist`. You should create it in the initializer for `UserData` instead. Your script should only ever create a single instance of `Spotify` for each Spotify user. The reason your are getting a "Couldn't read cache at <cache_path>" error may simply be because the first time you create an instance of `Spotify` the cache file does not exist. Have you checked whether it does exist? If the file does not exist and you are running the script for the first time (or the first time since you changed the cache path), then you can safely ignore this error. In order to provide more help I will need to see what your config file looks like. If you post it here, make sure to redact sensitive information, such as your client id and client secret.
Author
Owner

@Peter-Schorn commented on GitHub (Nov 8, 2020):

@stephanebruckert Is there a reason why a warning is emitted when the cache file does not exist at the specified path? When the script is being run for the first time, it should be expected that the cache file does not exist yet, so this shouldn't be considered an error condition. This behavior has confused me in the past as well.

<!-- gh-comment-id:723651954 --> @Peter-Schorn commented on GitHub (Nov 8, 2020): @stephanebruckert Is there a reason why a warning is emitted when the cache file does not exist at the specified path? When the script is being run for the first time, it should be expected that the cache file does not exist yet, so this shouldn't be considered an error condition. This behavior has confused me in the past as well.
Author
Owner

@stephanebruckert commented on GitHub (Nov 11, 2020):

@Peter-Schorn you are right it shouldn't show this warning if the file does not exist, only if it cannot be read (eg. no correct permission). We should change it, and possibly prepend all warnings with Warning: so that people don't think it's an error to worry too much about

<!-- gh-comment-id:725061684 --> @stephanebruckert commented on GitHub (Nov 11, 2020): @Peter-Schorn you are right it shouldn't show this warning if the file does not exist, only if it cannot be read (eg. no correct permission). We should change it, and possibly prepend all warnings with `Warning: ` so that people don't think it's an error to worry too much about
Author
Owner

@Peter-Schorn commented on GitHub (Nov 11, 2020):

@stephanebruckert I'll work on a PR to that effect.

<!-- gh-comment-id:725065067 --> @Peter-Schorn commented on GitHub (Nov 11, 2020): @stephanebruckert I'll work on a PR to that effect.
Author
Owner

@nahar-senior commented on GitHub (Nov 11, 2020):

Thank you, I will update as per your suggestion and share the output

<!-- gh-comment-id:725612915 --> @nahar-senior commented on GitHub (Nov 11, 2020): Thank you, I will update as per your suggestion and share the output
Author
Owner

@nahar-senior commented on GitHub (Nov 14, 2020):

Hi Peter,

I have made the changes that you suggested but I get the same error unfortunately. Here is my updated code:

import configparser
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import json
import os
import csv

class UserData():

    def __init__(self, config_path):
        config = configparser.ConfigParser()
        config.read(config_path)

        self.CLIENT_ID = config['AUTH']['cid']
        self.CLIENT_SECRET = config['AUTH']['secret']
        self.REDIRECT_URI = config['AUTH']['redirect_uri']
        self.USERNAME = config['AUTH']['username']
        self.CACHE = config['AUTH']['cache']
        self.HOME_DIR = config['PATH']['home_dir']
        self.top_artists = {}
        self.top_tracks = {}

        self.sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=self.CLIENT_ID,
                                                client_secret=self.CLIENT_SECRET,
                                                redirect_uri=self.REDIRECT_URI,
                                                scope="user-top-read", 
                                                username=self.USERNAME, 
                                                cache_path=self.CACHE))
        

    def get_top_artist(self, limit=None, time_range=None, offset=0):

        self.top_artists = self.sp.current_user_top_artists(limit=limit, offset=offset, time_range=time_range)

        with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.csv', 'w' ,newline='') as csvfile:

            writer = csv.writer(csvfile, delimiter = ',', quoting = csv.QUOTE_MINIMAL)
            writer.writerow(['sno', 'id', 'name', 'popularity', 'genre', 'uri', 'image_ref', 'follower_count'])

            for idx, item in enumerate(self.top_artists['items']):
                sno = idx
                id = item['id']
                name = item['name']
                popularity = item['popularity']
                genre = item['genres']
                uri = item['uri']
                image_ref = item['images'][2]['url']
                follower_count = item['followers']['total']

                writer.writerow([sno, id, name, popularity, genre, uri, image_ref, follower_count])

        with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.json', 'w') as myfile:
            print(myfile)
            json.dump(self.top_artists, myfile, indent=4, sort_keys=True)

        return self.top_artists

data = UserData(config_path='/Users/siddharthnahar/Dev/py_spotify/config.ini')
data.get_top_artist(limit=1)

Below is the config file:

[PATH]
home_dir = '/Users/siddharthnahar/Dev/py_spotify/'
src_dir = '/Users/siddharthnahar/Dev/py_spotify/src'

[AUTH]
cid='xxx'
secret='xxx'
redirect_uri='http://localhost:8888/callback'
username='xxx'
cache ='.cache-21ranjgq5en4j53pcqfcedopi'

[SCOPES]
read_playlist=playlist-read-private
read_library=user-library-read
top_artists=user-top-read

When I ran this script, I already had an .cache file in my directory. But I still get the below error:

siddharthnahar@Siddharths-MBP py_spotify % /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data2.py
Couldn't read cache at: '.cache-21ranjgq5en4j53pcqfcedopi'
Enter the URL you were redirected to: 

Here is the URL I'm directed to:

https://accounts.spotify.com/authorize?client_id=%<my_client_id>%27&response_type=code&redirect_uri=%27http%3A%2F%2Flocalhost%3A8888%2Fcallback%27&scope=user-top-read

<!-- gh-comment-id:727210606 --> @nahar-senior commented on GitHub (Nov 14, 2020): Hi Peter, I have made the changes that you suggested but I get the same error unfortunately. Here is my updated code: ```python import configparser import spotipy from spotipy.oauth2 import SpotifyOAuth import json import os import csv class UserData(): def __init__(self, config_path): config = configparser.ConfigParser() config.read(config_path) self.CLIENT_ID = config['AUTH']['cid'] self.CLIENT_SECRET = config['AUTH']['secret'] self.REDIRECT_URI = config['AUTH']['redirect_uri'] self.USERNAME = config['AUTH']['username'] self.CACHE = config['AUTH']['cache'] self.HOME_DIR = config['PATH']['home_dir'] self.top_artists = {} self.top_tracks = {} self.sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, redirect_uri=self.REDIRECT_URI, scope="user-top-read", username=self.USERNAME, cache_path=self.CACHE)) def get_top_artist(self, limit=None, time_range=None, offset=0): self.top_artists = self.sp.current_user_top_artists(limit=limit, offset=offset, time_range=time_range) with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.csv', 'w' ,newline='') as csvfile: writer = csv.writer(csvfile, delimiter = ',', quoting = csv.QUOTE_MINIMAL) writer.writerow(['sno', 'id', 'name', 'popularity', 'genre', 'uri', 'image_ref', 'follower_count']) for idx, item in enumerate(self.top_artists['items']): sno = idx id = item['id'] name = item['name'] popularity = item['popularity'] genre = item['genres'] uri = item['uri'] image_ref = item['images'][2]['url'] follower_count = item['followers']['total'] writer.writerow([sno, id, name, popularity, genre, uri, image_ref, follower_count]) with open(os.path.join(os.path.dirname(os.path.realpath(__file__)))+'/top_artist.json', 'w') as myfile: print(myfile) json.dump(self.top_artists, myfile, indent=4, sort_keys=True) return self.top_artists data = UserData(config_path='/Users/siddharthnahar/Dev/py_spotify/config.ini') data.get_top_artist(limit=1) ``` Below is the config file: ```python [PATH] home_dir = '/Users/siddharthnahar/Dev/py_spotify/' src_dir = '/Users/siddharthnahar/Dev/py_spotify/src' [AUTH] cid='xxx' secret='xxx' redirect_uri='http://localhost:8888/callback' username='xxx' cache ='.cache-21ranjgq5en4j53pcqfcedopi' [SCOPES] read_playlist=playlist-read-private read_library=user-library-read top_artists=user-top-read ``` When I ran this script, I already had an .cache file in my directory. But I still get the below error: ```python siddharthnahar@Siddharths-MBP py_spotify % /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 /Users/siddharthnahar/Dev/py_spotify/get_data2.py Couldn't read cache at: '.cache-21ranjgq5en4j53pcqfcedopi' Enter the URL you were redirected to: ``` Here is the URL I'm directed to: https://accounts.spotify.com/authorize?client_id=%<my_client_id>%27&response_type=code&redirect_uri=%27http%3A%2F%2Flocalhost%3A8888%2Fcallback%27&scope=user-top-read
Author
Owner

@stephanebruckert commented on GitHub (Nov 14, 2020):

When I ran this script, I already had an .cache file in my directory. But I still get the below error:

What is the exact name of the cache file? Is it .cache or is it .cache-21ranjgq5en4j53pcqfcedopi? It should be the later according to your code

The PR by @Peter-Schorn was merged to master, please use that version so we get better warnings / error messages and let us know what is shows

pip install git+https://github.com/plamere/spotipy.git --upgrade

I haven't tested your code yet, but I don't see anything that is too wrong. I just see you are still using the following the following:

username=self.USERNAME, 
cache_path=self.CACHE))

while these are optional. It should work with it, but since some work was done around it lately, perhaps there is a bug. Can you please remove these 2 lines and try again?

<!-- gh-comment-id:727211734 --> @stephanebruckert commented on GitHub (Nov 14, 2020): > When I ran this script, I already had an .cache file in my directory. But I still get the below error: What is the exact name of the cache file? Is it `.cache` or is it `.cache-21ranjgq5en4j53pcqfcedopi`? It should be the later according to your code The PR by @Peter-Schorn was merged to master, please use that version so we get better warnings / error messages and let us know what is shows pip install git+https://github.com/plamere/spotipy.git --upgrade I haven't tested your code yet, but I don't see anything that is too wrong. I just see you are still using the following the following: username=self.USERNAME, cache_path=self.CACHE)) while these are optional. It _should_ work with it, but since some work was done around it lately, perhaps there is a bug. Can you please remove these 2 lines and try again?
Author
Owner

@Peter-Schorn commented on GitHub (Nov 14, 2020):

@stephanebruckert @siddharthnahar The reason for the error is actually much simpler than you think. The config file should not have quotes around the values. If you print the values after you retrieve them from the file, you will see that the quotes are included as part of the values.

<!-- gh-comment-id:727232673 --> @Peter-Schorn commented on GitHub (Nov 14, 2020): @stephanebruckert @siddharthnahar The reason for the error is actually much simpler than you think. The config file should *not* have quotes around the values. If you print the values after you retrieve them from the file, you will see that the quotes are included as part of the values.
Author
Owner

@Peter-Schorn commented on GitHub (Nov 14, 2020):

Take a look at one of the errors you received:

Couldn't read cache at: '.cache-21ranjgq5en4j53pcqfcedopi'

The logger does not enclose the file path in quotes; the quotes are part of the value, which is clearly not what you want.

Take a look at the documentation for configparser for how to properly format the config file.

<!-- gh-comment-id:727233326 --> @Peter-Schorn commented on GitHub (Nov 14, 2020): Take a look at one of the errors you received: ``` Couldn't read cache at: '.cache-21ranjgq5en4j53pcqfcedopi' ``` The logger does not enclose the file path in quotes; the quotes are part of the value, which is clearly not what you want. Take a look at the [documentation for configparser][1] for how to properly format the config file. [1]: https://docs.python.org/3.9/library/configparser.html
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#362
No description provided.