Playback commands can repeatedly hit 429 during Retry-After cooldown

Author: adixgCreated Sep 18, 2026Updated Sep 18, 2026
Labelsenhancement

Is your feature already implemented in the latest master?

I checked the README/features and the recent rate-limit work in #1076 and #1077. I do not think this exact behavior is implemented.

From #1076, I understand that spotify-player now handles Spotify Web API 429 Too Many Requests centrally, respects Retry-After for GET requests, coalesces duplicate GETs, and avoids retrying mutation requests to prevent duplicate writes.

This request is specifically about what happens when new playback mutation commands are triggered while a Retry-After cooldown is already active.

Is your feature request related to a problem? Please describe.

Yes. After configuring a custom client_id, authentication and read requests work for me:

  • spotify_player get key devices succeeds
  • spotify_player get key user-playlists succeeds
  • the integrated spotify-player device appears in the device list
  • the custom client token is created successfully

The remaining problem is playback control commands such as play/pause/start/transfer/seek.

When Spotify returns 429 Too Many Requests with Retry-After, the app can still send more playback mutation requests during that cooldown window. In my logs, repeated ResumePause / StartPlayback requests hit 429 several times in the same short retry window.

Example log pattern:

WARN client_request{request=Player(ResumePause)}: spotify_player::client::middleware:
Spotify Web API rate limit encountered method=PUT
url=https://api.spotify.com/v1/me/player/play?device_id=...
retry_after_secs=6

ERROR client_request{request=Player(ResumePause)}:
spotify_player::client::handlers:
Failed to handle client request: http error: status code 429 Too Many Requests

Describe the solution you'd like

I am not suggesting automatic retries for mutation requests. I agree that blindly retrying mutations could duplicate writes or produce surprising playback state.

Instead, would it make sense for playback mutation commands to be cooldown-aware?

For example, if Spotify returns 429 with Retry-After, the app could store that cooldown. Until it expires, new playback mutation commands could be rejected locally or suppressed with a clear status/log message, such as:

Spotify is rate-limiting playback controls; retry after Ns.

Desired behavior:

  • GET requests keep using the existing retry/coalescing behavior.
  • Playback mutation requests are not automatically retried.
  • New playback mutation commands during an active cooldown are not sent to Spotify.
  • The app surfaces a clear message instead of repeatedly sending requests that are expected to fail.

Describe alternatives you've considered

I tried using a custom Spotify client_id. That fixed authentication/read behavior, but playback mutation requests can still hit 429.

I also tried increasing playback_refresh_duration_in_ms locally. That can reduce request pressure, but I do not think changing the default polling interval is the right upstream fix.

Automatically retrying mutation requests after Retry-After is another option, but I think that is riskier than suppressing new mutation commands during the cooldown.