Django Cron Job Error: “[Errno 98] Address Already in Use” When Using Spotify API with django-crontab

I am working on a Django project where I use a cron job to manage Spotify playlists using the Spotify API. The cron job is scheduled with django-crontab and is intended to add tracks to multiple Spotify playlists across different accounts.

Problem:
The cron job works fine up to a certain point, but I encounter the following error repeatedly:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>ERROR 2024-09-06 01:11:02,768 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 01:11:07,771 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 01:11:12,774 cron Error adding tracks: [Errno 98] Address already in use
</code>
<code>ERROR 2024-09-06 01:11:02,768 cron Error adding tracks: [Errno 98] Address already in use ERROR 2024-09-06 01:11:07,771 cron Error adding tracks: [Errno 98] Address already in use ERROR 2024-09-06 01:11:12,774 cron Error adding tracks: [Errno 98] Address already in use </code>
ERROR 2024-09-06 01:11:02,768 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 01:11:07,771 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 01:11:12,774 cron Error adding tracks: [Errno 98] Address already in use

What I have tried:

  • Environment: I am using Ubuntu with Django, django-crontab, and Spotipy (a Python client for the Spotify Web API).
  • Spotify Web API Sandbox: I tested the API with spotify web API and it works fine there.
  • Error Analysis: The error occurs after a log statement indicating that a user ID is being used to add tracks to a playlist. The next try block does not execute, and the [Errno 98] Address already in use error is raised.
  • Port Conflict Check: I initially thought the error might be due to port conflicts with the Django server running on port 8000, but I understand that my Django server is expected to run on this port, so checking for its usage is not necessary.
  • Error Handling and Retrying: I’ve implemented retry logic to handle exceptions such as Spotify API rate limits (429 Too Many Requests) and permission errors (403 Forbidden). The retry logic handles these exceptions correctly, but the [Errno 98] Address already in use error persists.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>def add_tracks_to_playlist(order, playlist_id, track_uris, sp, spotify_account):
retries = 3
delay = 5
USER_ID = spotify_account.spotify_key.username
logger.info(f"Using user ID {USER_ID} to add tracks to playlist {playlist_id}")
for attempt in range(retries):
try:
logger.debug(f"Attempting to add {len(track_uris)} tracks to playlist {playlist_id}, attempt {attempt + 1}")
sp.user_playlist_add_tracks(USER_ID, playlist_id, track_uris)
logger.info(f"Successfully added {len(track_uris)} tracks to playlist {playlist_id} for user {order.user_id}")
update_order_status(order)
break # Exit the loop if successful
except SpotifyException as e:
logger.error(f"Spotify API error: {e.msg}")
logger.debug(f"Spotify API response: {e}")
if e.http_status == 403:
logger.error(f"Check if the user {USER_ID} is correctly registered and has permissions to modify the playlist.")
return # Exit further retries as this is likely a permissions issue
if e.http_status == 429: # Rate limit exceeded
retry_after = int(e.headers.get('Retry-After', delay))
logger.info(f"Rate limit exceeded. Retrying after {retry_after} seconds.")
time.sleep(retry_after)
except OSError as e:
if e.errno == 98: # Address already in use
logger.error(f"Error adding tracks: Address already in use. Retrying after {delay} seconds.")
time.sleep(delay)
else:
logger.error(f"OS Error: {e}")
logger.debug(f"Detailed OS exception: {repr(e)}")
time.sleep(delay)
except Exception as e:
logger.error(f"Error adding tracks: {e}")
logger.debug(f"Detailed exception: {repr(e)}")
time.sleep(delay)
else:
logger.error(f"Failed to add tracks to playlist {playlist_id} after {retries} attempts.")
</code>
<code>def add_tracks_to_playlist(order, playlist_id, track_uris, sp, spotify_account): retries = 3 delay = 5 USER_ID = spotify_account.spotify_key.username logger.info(f"Using user ID {USER_ID} to add tracks to playlist {playlist_id}") for attempt in range(retries): try: logger.debug(f"Attempting to add {len(track_uris)} tracks to playlist {playlist_id}, attempt {attempt + 1}") sp.user_playlist_add_tracks(USER_ID, playlist_id, track_uris) logger.info(f"Successfully added {len(track_uris)} tracks to playlist {playlist_id} for user {order.user_id}") update_order_status(order) break # Exit the loop if successful except SpotifyException as e: logger.error(f"Spotify API error: {e.msg}") logger.debug(f"Spotify API response: {e}") if e.http_status == 403: logger.error(f"Check if the user {USER_ID} is correctly registered and has permissions to modify the playlist.") return # Exit further retries as this is likely a permissions issue if e.http_status == 429: # Rate limit exceeded retry_after = int(e.headers.get('Retry-After', delay)) logger.info(f"Rate limit exceeded. Retrying after {retry_after} seconds.") time.sleep(retry_after) except OSError as e: if e.errno == 98: # Address already in use logger.error(f"Error adding tracks: Address already in use. Retrying after {delay} seconds.") time.sleep(delay) else: logger.error(f"OS Error: {e}") logger.debug(f"Detailed OS exception: {repr(e)}") time.sleep(delay) except Exception as e: logger.error(f"Error adding tracks: {e}") logger.debug(f"Detailed exception: {repr(e)}") time.sleep(delay) else: logger.error(f"Failed to add tracks to playlist {playlist_id} after {retries} attempts.") </code>
def add_tracks_to_playlist(order, playlist_id, track_uris, sp, spotify_account):
    retries = 3
    delay = 5
    USER_ID = spotify_account.spotify_key.username

    logger.info(f"Using user ID {USER_ID} to add tracks to playlist {playlist_id}")

    for attempt in range(retries):
        try:
            logger.debug(f"Attempting to add {len(track_uris)} tracks to playlist {playlist_id}, attempt {attempt + 1}")
            sp.user_playlist_add_tracks(USER_ID, playlist_id, track_uris)
            logger.info(f"Successfully added {len(track_uris)} tracks to playlist {playlist_id} for user {order.user_id}")

            update_order_status(order)
            break  # Exit the loop if successful

        except SpotifyException as e:
            logger.error(f"Spotify API error: {e.msg}")
            logger.debug(f"Spotify API response: {e}")

            if e.http_status == 403:
                logger.error(f"Check if the user {USER_ID} is correctly registered and has permissions to modify the playlist.")
                return  # Exit further retries as this is likely a permissions issue

            if e.http_status == 429:  # Rate limit exceeded
                retry_after = int(e.headers.get('Retry-After', delay))
                logger.info(f"Rate limit exceeded. Retrying after {retry_after} seconds.")
                time.sleep(retry_after)

        except OSError as e:
            if e.errno == 98:  # Address already in use
                logger.error(f"Error adding tracks: Address already in use. Retrying after {delay} seconds.")
                time.sleep(delay)
            else:
                logger.error(f"OS Error: {e}")
                logger.debug(f"Detailed OS exception: {repr(e)}")
                time.sleep(delay)

        except Exception as e:
            logger.error(f"Error adding tracks: {e}")
            logger.debug(f"Detailed exception: {repr(e)}")
            time.sleep(delay)

    else:
        logger.error(f"Failed to add tracks to playlist {playlist_id} after {retries} attempts.")

Cronjob log

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>INFO 2024-09-06 15:29:01,639 cron Cron started
INFO 2024-09-06 15:29:01,640 cron Cron job started.
INFO 2024-09-06 15:29:01,644 cron 1 pending orders found.
INFO 2024-09-06 15:29:01,646 cron Processing Order ID 35 with 1 playlists.
INFO 2024-09-06 15:29:01,653 cron Initializing Spotify client for user myuserid with Client ID: myclientid
INFO 2024-09-06 15:29:01,654 cron Successfully initialized SpotifyOAuth for user.
INFO 2024-09-06 15:29:01,654 cron Assigned jobs: [1]
INFO 2024-09-06 15:29:01,655 cron Distributing 1 playlists to job scheduled at 2024-09-06 15:38:01.655010 for Order ID 35.
INFO 2024-09-06 15:29:01,655 cron Adding track 4jYwFHigUt3c21ATMklTku to playlist 4ZwEDixe0VTBSCHfLLqKoH
ERROR 2024-09-06 15:29:01,659 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 15:29:06,662 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 15:29:11,668 cron Error adding tracks: [Errno 98] Address already in use
</code>
<code>INFO 2024-09-06 15:29:01,639 cron Cron started INFO 2024-09-06 15:29:01,640 cron Cron job started. INFO 2024-09-06 15:29:01,644 cron 1 pending orders found. INFO 2024-09-06 15:29:01,646 cron Processing Order ID 35 with 1 playlists. INFO 2024-09-06 15:29:01,653 cron Initializing Spotify client for user myuserid with Client ID: myclientid INFO 2024-09-06 15:29:01,654 cron Successfully initialized SpotifyOAuth for user. INFO 2024-09-06 15:29:01,654 cron Assigned jobs: [1] INFO 2024-09-06 15:29:01,655 cron Distributing 1 playlists to job scheduled at 2024-09-06 15:38:01.655010 for Order ID 35. INFO 2024-09-06 15:29:01,655 cron Adding track 4jYwFHigUt3c21ATMklTku to playlist 4ZwEDixe0VTBSCHfLLqKoH ERROR 2024-09-06 15:29:01,659 cron Error adding tracks: [Errno 98] Address already in use ERROR 2024-09-06 15:29:06,662 cron Error adding tracks: [Errno 98] Address already in use ERROR 2024-09-06 15:29:11,668 cron Error adding tracks: [Errno 98] Address already in use </code>
INFO 2024-09-06 15:29:01,639 cron Cron started
INFO 2024-09-06 15:29:01,640 cron Cron job started.
INFO 2024-09-06 15:29:01,644 cron 1 pending orders found.
INFO 2024-09-06 15:29:01,646 cron Processing Order ID 35 with 1 playlists.
INFO 2024-09-06 15:29:01,653 cron Initializing Spotify client for user myuserid with Client ID: myclientid
INFO 2024-09-06 15:29:01,654 cron Successfully initialized SpotifyOAuth for user.
INFO 2024-09-06 15:29:01,654 cron Assigned jobs: [1]
INFO 2024-09-06 15:29:01,655 cron Distributing 1 playlists to job scheduled at 2024-09-06 15:38:01.655010 for Order ID 35.
INFO 2024-09-06 15:29:01,655 cron Adding track 4jYwFHigUt3c21ATMklTku to playlist 4ZwEDixe0VTBSCHfLLqKoH
ERROR 2024-09-06 15:29:01,659 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 15:29:06,662 cron Error adding tracks: [Errno 98] Address already in use
ERROR 2024-09-06 15:29:11,668 cron Error adding tracks: [Errno 98] Address already in use

According to the log cronjob works fine till this line of code logger.info(f"Using user ID {USER_ID} to add tracks to playlist {playlist_id}") but when it tries to add song into spotify playlist using spotipy function sp.user_playlist_add_tracks(USER_ID, playlist_id, track_uris) it gives me OS Error 98

Additional Information:

sudo lsof -i -n -P | grep LISTEN

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>systemd-r 605 systemd-resolve 14u IPv4 18718 0t0 TCP 127.0.0.53:53 (LISTEN)
cupsd 916 root 6u IPv6 21045 0t0 TCP [::1]:631 (LISTEN)
cupsd 916 root 7u IPv4 21046 0t0 TCP 127.0.0.1:631 (LISTEN)
postman-a 13327 a-h-m-a-r 71u IPv4 111201 0t0 TCP 127.0.0.1:10533 (LISTEN)
python 25924 a-h-m-a-r 8u IPv4 224162 0t0 TCP 127.0.0.1:8000 (LISTEN)
</code>
<code>systemd-r 605 systemd-resolve 14u IPv4 18718 0t0 TCP 127.0.0.53:53 (LISTEN) cupsd 916 root 6u IPv6 21045 0t0 TCP [::1]:631 (LISTEN) cupsd 916 root 7u IPv4 21046 0t0 TCP 127.0.0.1:631 (LISTEN) postman-a 13327 a-h-m-a-r 71u IPv4 111201 0t0 TCP 127.0.0.1:10533 (LISTEN) python 25924 a-h-m-a-r 8u IPv4 224162 0t0 TCP 127.0.0.1:8000 (LISTEN) </code>
systemd-r   605 systemd-resolve   14u  IPv4  18718      0t0  TCP 127.0.0.53:53 (LISTEN)
cupsd       916            root    6u  IPv6  21045      0t0  TCP [::1]:631 (LISTEN)
cupsd       916            root    7u  IPv4  21046      0t0  TCP 127.0.0.1:631 (LISTEN)
postman-a 13327       a-h-m-a-r   71u  IPv4 111201      0t0  TCP 127.0.0.1:10533 (LISTEN)
python    25924       a-h-m-a-r    8u  IPv4 224162      0t0  TCP 127.0.0.1:8000 (LISTEN)
  • The error occurs intermittently and seems to be related to network or socket handling.
  • The cron job is designed to run at specific intervals, and I have a cache-based lock to ensure only one instance runs at a time.

My Setup:

  • Django Version: latest
  • Python Version: 3.12
  • Spotipy for adding songs to playlist
  • OS: Ubuntu 20.04
  • Tools: django-crontab for scheduling the cron job

Question:

  • What could be causing the [Errno 98] Address already in use error within the context of my cron job?
  • How can I modify my code or cron job setup to avoid this error while ensuring reliable execution of my task?
  • Are there best practices or alternative approaches for handling such network-related errors in a cron job environment in Django?

Wget Request Sample:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>wget --quiet
--method POST
--header 'Content-Type: application/json'
--header 'Authorization: Bearer 1POdFZRZbvb...qqillRxMr2z'
--body-data '{n "uris": [n "3yHyiUDJdz02FZ6jfUbsmY"n ],n "position": 0n}'
--output-document
- 'https://api.spotify.com/v1/playlists/4ZwEDixe0VTBSCHfLLqKoH/tracks?uris=spotify%3Atrack%3A3yHyiUDJdz02FZ6jfUbsmY'
</code>
<code>wget --quiet --method POST --header 'Content-Type: application/json' --header 'Authorization: Bearer 1POdFZRZbvb...qqillRxMr2z' --body-data '{n "uris": [n "3yHyiUDJdz02FZ6jfUbsmY"n ],n "position": 0n}' --output-document - 'https://api.spotify.com/v1/playlists/4ZwEDixe0VTBSCHfLLqKoH/tracks?uris=spotify%3Atrack%3A3yHyiUDJdz02FZ6jfUbsmY' </code>
wget --quiet 
  --method POST 
  --header 'Content-Type: application/json' 
  --header 'Authorization: Bearer 1POdFZRZbvb...qqillRxMr2z' 
  --body-data '{n    "uris": [n        "3yHyiUDJdz02FZ6jfUbsmY"n    ],n    "position": 0n}' 
  --output-document 
  - 'https://api.spotify.com/v1/playlists/4ZwEDixe0VTBSCHfLLqKoH/tracks?uris=spotify%3Atrack%3A3yHyiUDJdz02FZ6jfUbsmY'

Crontab setup in settings.py

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>CRONJOBS = [
('*/5 * * * *', 'app.cronjob.cron.my_scheduled_job'),
]
CRONTAB_LOCK_JOBS = True
</code>
<code>CRONJOBS = [ ('*/5 * * * *', 'app.cronjob.cron.my_scheduled_job'), ] CRONTAB_LOCK_JOBS = True </code>
CRONJOBS = [
    ('*/5 * * * *', 'app.cronjob.cron.my_scheduled_job'),
]
CRONTAB_LOCK_JOBS = True

0

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật