From 461f28f0841ef3c8c72130e37883c77d923fb9fe Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Sat, 18 Apr 2026 20:46:22 -0700 Subject: [PATCH] Fix Spotify OAuth stealing ports in Docker on fresh installs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When no cached token exists, spotipy's auth probe starts an interactive OAuth flow that binds 127.0.0.1: inside the container. This either steals Flask's port 8008 (crash loop) or binds loopback-only on 8888 (unreachable from Docker host — 'connection reset by peer'). Now checks for a cached token before probing. If none exists, returns False immediately so users authenticate via the SoulSync web UI instead. No behavior change for already-authenticated users. Fixes #269 --- core/spotify_client.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/spotify_client.py b/core/spotify_client.py index 0e2c962e..ddcb1d09 100644 --- a/core/spotify_client.py +++ b/core/spotify_client.py @@ -620,6 +620,21 @@ class SpotifyClient: return self._auth_cached_result # Cache miss — make API call outside the lock. + # Safety: if there's no cached token, return False immediately. + # Without this guard, spotipy's auth_manager will try to start an interactive + # OAuth flow (binding 127.0.0.1:), which inside Docker either + # steals Flask's port (crash loop) or binds loopback-only (unreachable from host). + # Users authenticate via the SoulSync web UI instead. + try: + cache_handler = getattr(self.sp.auth_manager, 'cache_handler', None) + if cache_handler and cache_handler.get_cached_token() is None: + with self._auth_cache_lock: + self._auth_cached_result = False + self._auth_cache_time = time.time() + return False + except Exception: + pass + # Use a dedicated probe client (retries=0) so a 429 here propagates # immediately and we can detect long Retry-After bans. try: